public event EventHandler<EventArgs> MyEventToBeFired;
public void FireEvent(Guid instanceId, string handler)
{
// Note: this is being fired from a method with in the same
// class that defined the event (that is, "this").
EventArgs e = new EventArgs(instanceId);
MulticastDelegate eventDelagate =
(MulticastDelegate)this.GetType().GetField(handler,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic).GetValue(this);
Delegate[] delegates = eventDelagate.GetInvocationList();
foreach (Delegate dlg in delegates)
{
dlg.Method.Invoke(dlg.Target, new object[] { this, e });
}
}
FireEvent(new Guid(), "MyEventToBeFired");
public static void RaiseEvent<TEventArgs>(this object source, string eventName, TEventArgs eventArgs)
where TEventArgs : EventArgs
{
// Find the delegate and invoke it.
var delegateField = FindField(source.GetType(), eventName);
var eventDelegate = delegateField?.GetValue(source) as Delegate;
eventDelegate?.DynamicInvoke(source, eventArgs);
// This local function searches the class hierarchy for the delegate field.
FieldInfo FindField(Type type, string name)
{
while (true)
{
var field = type.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
return field;
}
var baseType = type.BaseType;
if (baseType == null)
{
return null;
}
type = baseType;
}
}
}
9条答案
按热度按时间j7dteeu81#
下面是一个使用泛型的演示(省略了错误检查):
dauxcl2d2#
一般来说,你不能这样做。可以把事件看作基本上是一对
AddHandler
/RemoveHandler
方法(因为这就是它们的本质)。如何实现它们取决于类。大多数WinForms控件使用EventHandlerList
作为它们的实现,但是如果你的代码开始获取私有字段和键,它将非常脆弱。ButtonEdit
控件是否公开了可以调用的OnClick
方法?脚注:事实上,事件 * 可以 * 有“raise”成员,因此
EventInfo.GetRaiseMethod
。然而,这从来没有被C#填充过,我也不相信它在框架中。bvpmtnay3#
你通常不能引发另一个类的事件。事件实际上是作为一个私有的委托字段存储的,外加两个访问器(add_event和remove_event)。
要通过反射来实现这一点,只需找到私有委托字段,获取它,然后调用它。
cbwuti444#
I wrote an extension to classes, which implements INotifyPropertyChanged to inject the RaisePropertyChange method, so I can use it like this:
而不在任何基类中实现该方法。对于我的使用来说,它很慢,但也许源代码可以帮助一些人。
这就是:
我删除了原始代码的一些部分,所以扩展应该可以正常工作,没有引用我的库的其他部分。
有些代码是从别人那里借来的。真丢人,我忘了是从哪里得到的
3vpjnl9f5#
从 Raising an event via reflection 中,尽管我认为VB.NET中的答案,也就是说,在这篇文章之前的两篇文章将为您提供通用方法(例如,我将从VB.NET的一篇文章中寻找引用不在同一个类中的类型的灵感):
hivapdat6#
Wiebe Cnossen的accepted answer代码似乎可以简化为:
y3bcpkx17#
事实证明,我可以做到这一点,但却没有意识到:
但如果我不能,我就必须深入研究源代码,找到引发事件的方法。
谢谢你们的帮助。
shyt4zoc8#
如果你知道控件是一个按钮,你可以调用它的
PerformClick()
方法。我对其他事件也有类似的问题,比如OnEnter
,OnExit
。如果我不想为每个控件类型派生一个新类型,我就不能引发这些事件。xdnvmnnf9#
对一些现有答复和评论的进一步完善。
这也考虑到委托字段可能是在继承类上定义的。