vendredi 4 novembre 2016

Converting instance of Interface with generic method to Action

I'm struggling to create instances of Action<> using the MethodInfo's I can retrieve using reflection.

Using the example below I can easily call a custom method on my objects, but I would really like to convert them to Actions.

I have tried doing it by using Delegate.CreateDelegate but I can't seem to get this to return an Action with a generic type.

Example

I have created the following interface:

interface IMyTest { } // Marker interface
interface<TInput> IMyTest : IMyTest {
    void MyMethod(TInput input);
}

Then I inherit the interface in a class:

class MyClass : IMyTest<DateTime>, IMyTest<int> {
    void MyMethod(DateTime input) {
        // Do something
    }
    void MyMethod(int input) {
        // Do something else
    }
}

And then I create a method that uses reflection to find and call "MyMethod" from the interface instance:

void DoCallMyMethod(object target, object input) {
    IEnumerable<Type> interfaces = target.GetType().GetInterfaces()
        .Where(x => typeof(IMyTest).IsAssignableFrom(x) && x.IsGenericType);

    foreach (Type @interface in interfaces) {
        Type type = @interface.GetGenericArguments()[0];
        MethodInfo method = @interface.GetMethod("MyMethod", new Type[] { type });

        if (method != null) {
            method.Invoke(target, new[] { input });
        }
    }
}

And finally I put it all together:

MyClass foo = new MyClass();
DoCallMyMethod(foo, DateTime.Now);
DoCallMyMethod(foo, 47);

What I would want

Inside DoCallMyMethod I would like MethodInfo method to be converted to a generic Action so that the result would be something like this:

Action<type> myAction = method;

But this obviously doesn't work.

I found some similar SO posts (but none that cover exactly my case) that ended up with an answer similar to this:

Action<object> action = 
    (Action<object>)Delegate.CreateDelegate(typeof(Action<object>), target, method);

But this doesn't work because "Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type."

How can I get an Action with the specified type as its input type, while still retaining the object references (without new instances appearing)?





Aucun commentaire:

Enregistrer un commentaire