简体   繁体   English

使用Type和Template参数通过反射设置事件处理程序

[英]Set Event-Handler by reflection with Type and Template argument

I would like to set an event handler only by reflection, I can get all the types but I can't achieve it. 我只想通过反射来设置事件处理程序,我可以获取所有类型,但无法实现。

public delegate void MyHandler<T>(IMyInterface<T> pParam);    
public interface IMyInterface<T> 
{
    MyHandler<T> EventFired { get; set; }
}

void myFunction()
{
    //admit vMyObject is IMyInterface<ClassA>
    var vMyObject = vObj as IMyInterface<ClassA>;
    //get the generic type => ClassA
    var vTypeGeneric = vTypeReturn.GenericTypeArguments.FirstOrDefault();
    //build the type handler for the event MyHandler<ClassA>
    Type vAsyncOP = typeof(MyHandler<>).MakeGenericType(vTypeGeneric);

    // here I don't know how to create the Event handler to set EventFired 
    // dynamically with the code inside 

    var vEventFired = vMyObject.GetType().GetProperty("EventFired");
    vEventFired.SetMethod etc...

}

I found some code with the usage of Lambda/Expression but I don't understand how to use it in this case. 我发现了一些使用Lambda / Expression的代码,但在这种情况下我不明白如何使用它。

Full sample: 完整样本:

public delegate void MyHandler<T>(IMyInterface<T> pParam);

public interface IMyInterface<T>
{
    MyHandler<T> EventFired { get; set; }
}

public class MyClass : IMyInterface<int>
{
    public MyHandler<int> EventFired { get; set;}
}

public void ConcreteHandler(IMyInterface<int> p)
{
    Console.WriteLine("I'm here");
}

void Main()
{
    var myValue = new MyClass();
    var deleg = Delegate.CreateDelegate(typeof(MyHandler<int>), this, "ConcreteHandler");
    myValue.GetType().GetProperty("EventFired").SetValue(myValue, deleg);

    // Test delegate invocation:
    myValue.EventFired.Invoke(new MyClass());
}

Since the question asks about setting an event and the code refers to delegate, here is the code for setting an event using reflection (via extension method): 由于该问题询问有关设置事件的问题,并且代码涉及委托,因此以下是使用反射(通过扩展方法)设置事件的代码:

public delegate void MyHandler<T>(IMyInterface<T> pParam);
public interface IMyInterface<T>
{
    event MyHandler<T> EventFired;
}

public class ClassA : IMyInterface<int>
{
    public event MyHandler<int> EventFired;
    private int _Count = 0;
    public void Fire()
    {
        var handler = EventFired;
        if (handler != null) handler(this);
    }

    public override string ToString()
    {
        return "Call: " + (++_Count).ToString();
    }
}

public static class Extension
{
    public static void Add<T>(this IMyInterface<T> i, System.Reflection.MethodInfo method, object method_instance = null)
    {
        if (method.IsGenericMethodDefinition) method = method.MakeGenericMethod(typeof(T));
        Delegate d = Delegate.CreateDelegate(typeof(MyHandler<>).MakeGenericType(typeof(T)), method_instance, method);
        i.GetType().GetEvent("EventFired").GetAddMethod().Invoke(i, new object[] { d });
    }
}
public class Program
{
    public static void Print<T>(IMyInterface<T> val)
    {
        string output = val.ToString();
        Console.WriteLine(output);
        System.Diagnostics.Debug.WriteLine(output);
    }
    static void Main(string[] args)
    {
        ClassA ca = new ClassA();
        ca.EventFired += Print<int>;
        ca.Add(typeof(Program).GetMethod("Print", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public));
        ca.Fire();
    }
}

Sorry for the title, I meant not an event but a delegate property. 对不起标题,我的意思不是事件,而是委托属性。 I found the solution meanwhile : 我同时找到了解决方案:

public void MyDelegate<T>(IMyInterface<T> pParam)
{

}

void myFunction()
{
    //admit vMyObject is IMyInterface<ClassA>
    var vMyObject = vObj as IMyInterface<ClassA>;
    //get the generic type => ClassA
    var vTypeGeneric = vTypeReturn.GenericTypeArguments.FirstOrDefault();
    //build the type handler for the event MyHandler<ClassA>
    Type vAsyncOP = typeof(MyHandler<>).MakeGenericType(vTypeGeneric);

    // SOLUTION here :
    // Create MyDelegate<vTypeGeneric>
    // Then instanciate it with CreateDelegate and typeof(IMyInterface<vTypeGeneric>)

    var vMyDelegate= this.GetType().GetMethod("MyDelegate");
    var vMyDelegateGeneric = vMyDelegate.MakeGenericMethod(vTypeGeneric);
    Type vTypeHandlerGeneric = typeof(IMyInterface<>).MakeGenericType(vTypeGeneric);
    // this => bind to method in the class
    var vMethodDelegate = vMyDelegateGeneric.CreateDelegate(vTypeHandlerGeneric, this);

    // Set delegate Property
    var vEventFired = vMyObject.GetType().GetProperty("EventFired");
    vEventFired.SetValue(value, vDelegate);

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM