2017-10-02 4 views
0

리플렉션으로 이벤트 핸들러를 설정하고 싶습니다. 모든 유형을 얻을 수는 있지만 얻을 수는 없습니다.형식 및 템플릿 인수로 반사에 의한 이벤트 처리기 설정

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... 

} 

람다/표현식을 사용하여 일부 코드를 발견했지만이 경우이 코드를 사용하는 방법을 모르겠습니다.

답변

0

제목에 대해 유감스럽게 생각하지만 이벤트가 아니라 대리인 속성을 의미했습니다. 내가 그 사이에 해결책을 발견 : 근처

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); 

} 
0

전체 샘플 :

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()); 
} 
+0

용액으로부터를, 그것은 일반을 그리워하지만 아래의 솔루션을 게시 할 수 있습니다. 도와 줘서 고마워. – Poppyto

0

문제가 이벤트를 설정하는 방법에 대한 요청 및 코드 (확장 방법을 통해) 반사를 사용하여 이벤트를 설정하는 코드를 여기에 위임하는 의미이기 때문에 :

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(); 
    } 
} 
+0

내 실수, 그것은 대의원에 관한 것이 었습니다. 그 동안 해결책을 찾았으며 아래에 게시했습니다. 도움 주셔서 감사합니다. – Poppyto