views:

79

answers:

2

Let me try to give a little example.

class Session (
    public delegate string CleanBody();
    public static void Execute(string name, string q, CleanBody body) ...

can be used like:

Session.Execute("foo", "bar", delegate() { string x="beep"; /* whatever*/ return x; });

But what if I need to run is via MethodInfo.Invoke -- as in different dll no type dependencies either way. Like:

Type type = Type.GetType("Bla.Session, FooSessionDll", true);
MethodInfo methodInfo = type.GetMethod("Execute");

Object [] args = { "foo", "bar", delegate() // Doesn't compile, now that ?
{
    string x="beep"; /* whatever*/ return x;
}

methodInfo.Invoke("Trial Execution :-)", args);

Whatever trick/cast would be applied it would have to be such that it still arrives at Execute as a genuine delegate. Actual delegate(s) may have more complex signatures etc. etc.

A: 
private static class Invoker
{
    private static string Method()
    {
        return "beep";
    }

    public static object Invoke()
    {
        Type type = Type.GetType("Bla.Session, FooSessionDll", true);
        MethodInfo methodInfo = type.GetMethod("Execute");
        Type delegateType = methodInfo.GetParameters()[2].ParameterType;
        Delegate delegateInstance = Delegate.CreateDelegate(delegateType, typeof(Invoker).GetMethod("Method"));
        object[] args = new object[] { "foo", "bar", delegateInstance };
        return methodInfo.Invoke(null, args);
    }
}
ChaosPandion
That would inject a type dependency from that "other" dll. It's not an academic question :-) dll A (using Invoke) should conpile and run even if dll B (with Session.Execute) doesn't exist at all. Anything with anonymous types maybe?
ZXX
@zb_z - I think this may help you, although your question is not very clear.
ChaosPandion
Hmm, that methodInfo.GetParameters()[2].ParameterType looks promising, if there would be a way to cast delegate() { ....} to it. Actual delegate involved uses quite a number of objects from it's closure, so it's not exactly replacable by a static method, unless we had curing which we don't :-)
ZXX
A: 

OK, found the solution: Func<>, and the whole family of Func templates. In terms of the example I posted, converting the signature of Execute(...) to:

public static void Execute(string name, string q, Func<string> body) 

is functionally equivalent to the one with explicitly named delegate i.e. any code taking the type dependency on it can still use

Session.Execute("foo", "bar", delegate() { ... });

with zero code change, and any independent dll can now do:

Func<string> d = delegate() { .....} 

and pass it in an Object[] as a normal argument.

There was another thread asking "What’s so great about Func<>" -- well this is :-)

It allows breaking dependencies and unholy tie-ups with zero code change for existing code that uses it. One condition is that existing code used anonymous methods (like in example) and not old-style explicit delegate creation.

ZXX