0

I need to create an Expression<Action> that represents calling a method on a class.

As input, I have a string that describes the assembly and class name (standard fully-qualified class name) and another string that defines the method to invoke.

The class/method to be invoked are NOT actually available in the code where the Expression has to be created, so I can't just write ()=>MyClass.Invoke(); -- I don't have MyClass's assembly as a reference.

Scott Stafford
  • 43,764
  • 28
  • 129
  • 177
  • So you need to reflect on the assembly by name, look up the class by name, and then the member by name. Once you have that `MethodInfo`, you can call `MethodInfo.Invoke` – Peter Ritchie Oct 02 '14 at 18:59
  • In which case, most of what you are asking is duplicated in http://stackoverflow.com/questions/1137781/c-sharp-correct-way-to-load-assembly-find-class-and-call-run-method – Peter Ritchie Oct 02 '14 at 19:00
  • The assembly is not available at all. It's on another server. – Scott Stafford Oct 02 '14 at 19:04
  • Either you have to get the assembly on the local machine, or make an expression that details doing all that reflection. – Peter Ritchie Oct 02 '14 at 19:07
  • It is possible to write it with reflection. It will be ok for compile time. However, as Peter says, the assembly must be available at runtime. – Beemen Oct 02 '14 at 19:12
  • How do you write it with reflection? That's the question. In order to invoke the Expression, it would need to be available at runtime, but I'm not going to invoke it (at least, not before serializing it and shipping it to another process.) – Scott Stafford Oct 02 '14 at 20:40
  • What are you actually trying to do? I've never seen a problem whose most obvious solution is reflection not end up being an architectural problem rather than a legitimate reason to use reflection. If you need a class to create a `listener` then you should be using the eventbus pattern, not trying this reflection. – C Bauer Oct 03 '14 at 13:09
  • We'll probably give up this approach, but the point is to try to conform to Hangfire's (http://hangfire.io/) available API. Hangfire queues jobs via `Expression` and serializes the reflected MethodInfo into the database, where a task server later runs it. We want to separate the task server from the queuer, so the queuer need not have the code available to actually perform the task. – Scott Stafford Oct 03 '14 at 18:08

1 Answers1

1
System.Action act = () =>
{
    var typeName = "";
    var methodName = "";

    var type = System.Type.GetType(typeName);
    var method = type.GetMethod(methodName);

    object[] constructorArgs = null;
    var obj = type.InvokeMember(null,  System.Reflection.BindingFlags.CreateInstance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance, null, null, constructorArgs);

    object [] methodArgs = null;
    method.Invoke(obj, methodArgs);
};
System.Linq.Expressions.Expression<System.Action> exp = () => act();
exp.Compile()();
Beemen
  • 88
  • 7
  • That's brilliant - I didn't think of shipping the "thing that makes the thing" inside the expression, I was thinking of making the Action first and putting that in the expression. I'm not sure this will work for me specifically, but I'll give it a whirl. Either way, thanks and +1. – Scott Stafford Oct 03 '14 at 13:06
  • Your are most welcome. Hopefully it works for your case. – Beemen Oct 03 '14 at 13:27