C#代表和事件

时间:2009-03-05 11:16:47

标签: c# .net

我有一个带有类的程序集,该类使用委托和自定义事件args定义自定义事件。现在我必须通过我的代码动态加载此程序集并创建此类的实例。直到这里我很好。现在我必须使用自定义委托为类对象引发的事件提供事件处理程序。如何使用Relection为从类引发的事件添加事件处理程序?

4 个答案:

答案 0 :(得分:3)

以下是执行此操作的代码:

 class Program
  {
    static void Main(string[] args)
    {
      // Create publisher.
      var pub = Activator.CreateInstance(typeof(Publisher));
      // Get the event.
      var addEvent = typeof(Publisher).GetEvent("Event");

      // Create subscriber.
      var sub = Activator.CreateInstance(typeof(Subscriber));
      // Get the method.
      var handler = typeof(Subscriber).GetMethod("Handle");
      // Create a valid delegate for it.
      var handlerDelegate = MakeEventHandlerDelegate(handler, sub);

      // Add the event.
      addEvent.AddEventHandler(pub, handlerDelegate);

      // Call the raise method.
      var raise = typeof(Publisher).GetMethod("Raise");
      raise.Invoke(pub, new object[] { "Test Value" });
      Console.ReadLine();
    }

    static Delegate MakeEventHandlerDelegate(MethodInfo methodInfo, object target)
    {
      ParameterInfo[] info = methodInfo.GetParameters();
      if (info.Length != 2)
        throw new ArgumentOutOfRangeException("methodInfo");
      if (!typeof(EventArgs).IsAssignableFrom(info[1].ParameterType))
        throw new ArgumentOutOfRangeException("methodInfo");
      if (info[0].ParameterType != typeof(object))
        throw new ArgumentOutOfRangeException("methodInfo");

      return Delegate.CreateDelegate(typeof(EventHandler<>).MakeGenericType(info[1].ParameterType), target, methodInfo);
    }
  }

  class Args : EventArgs
  {
    public string Value { get; set; }
  }

  class Publisher
  {
    public event EventHandler<Args> Event;

    public void Raise(string value)
    {
      if (Event != null)
      {
        Args a = new Args { Value = value };
        Event(this, a);
      }
    }
  }

  class Subscriber
  {
    public void Handle(object sender, Args args)
    {
      Console.WriteLine("Handle called with {0}.", args.Value);
    }
  }

答案 1 :(得分:1)

事件是一个多播委托,您将检索该事件作为一种System.Delegate使用Delegate.Combine来组合这两个实例,然后将委托设置为组合委托。

C#有一个很好的速记语法:

class SomeClass
{
    public event Action<string> TextEvent;
}

你会写这样的东西:(我感觉有点懒,不会检查这个,你必须自己解决问题)

var obj = // instance of SomeClass...
var t = typeof(SomeClass); // you need the type object
var member = t.GetEvent("TextEvent"); 
member.AddEventHandler(obj, new Action<string>(delegate(string s)){}); // done!

答案 2 :(得分:0)

我以前必须这样做,真的很痛苦 - 最终遇到了这个tutorial

是否可以在另一个程序集中使用一个接口,以便使用反射来连接事件?只是一个想法...

答案 3 :(得分:0)

我可能遗漏了一些东西,但是如果你知道你需要连接的事件的名称和签名,那么可能你知道暴露该事件的类型。在这种情况下,为什么需要使用反射?只要您具有正确类型的引用,就可以以正常方式附加处理程序。