使用WebForms和CodeBehind通过反射引发事件

3

我知道有很多关于通过反射触发事件的问题,但是我没有找到以下问题的答案[我怀疑答案是否定的]:

在给定一个“标准”事件声明的情况下,是否有任何方法可以通过字符串字面量引用来触发事件。

例如,伪代码:

Dim eventName As String = "TestEvent"
RaiseEvent eventName

显然那样行不通。

我可以使用以下代码获取事件处理程序/多路广播委托的类型:

Me.GetType.GetEvent("TestEvent").GetAddMethod.GetParameters(0).Name
// "TestEventEventHandler

但我找不到页面对象上的实例来调用.GetInvocationList

这类似于这个问题:如何从VB.NET中的事件中获取实际的EventHandler委托实例?

然而,这里我特别关注的是通过一个字符串引发事件。

编辑:

在vb.net / webforms环境中有几件事情不同。根据我对接受答案的评论,由于代码后台模型的性质,不可能从Me.GetType()返回与事件对应的字段,因为在运行时Me指的是.aspx文件中继承类,而不是.aspx.vb文件中的类。

实际上,这意味着我必须使用Me.BaseType.GetType()来查找该字段。

第二件与最终答案无关的不同之处在于,在c#中,您可以直接引用事件处理程序MulticastDelegate,而在vb.net中,您不能这样做——或者至少要使用一种不受intellisense支持的未记录功能,如:如何从VB.NET中的事件中获取实际的EventHandler委托实例?


我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
好的,谢谢。我这里有一个问题 - 这是一个特定的vb.net/asp.net问题,因为c#/winforms的解决方案与vb.net/webforms的解决方案不同。我应该在标题中反映这个必要的问题还是只在问题中反映?我觉得这会误导人,让人以为这个问题是一个通用的“.net事件通过反射”问题。 - mrmillsy
目前,我已经编辑了问题,以反映WebForms / VB.NET带来的困难。 - mrmillsy
从重新阅读您提供的帖子后,我已经更新了标题。您认为这样更合适吗? - mrmillsy
好多了。你已经将元数据转化为数据。 - John Saunders
2个回答

1

您可以在类型实例上调用GetField,然后继续在返回的FieldInfo上调用GetValue()。以下是一个示例(使用C#编写,因为我不会说vb.net)

class Foo
{
    public event EventHandler Bar;

}
class Program
{
    static void Main(string[] args)
    {
        var foo = new Foo();
        foo.Bar += FooOnBar;

        var ev = (MulticastDelegate)foo.GetType().GetField("Bar", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(foo);
        if (ev != null)
        {
            foreach (var del in ev.GetInvocationList())
            {
                del.Method.Invoke(del.Target, new object[] {foo, new EventArgs()});
            }
        }
        Console.ReadLine();
    }

    private static void FooOnBar(object sender, EventArgs eventArgs)
    {
        Console.WriteLine("Invoked!");
    }
}

谢谢,这似乎是答案,所以我会点赞,但我认为它没有准确考虑到WebForms的概念,这就是使这个问题与其他类似答案不同的地方,例如https://dev59.com/SHVC5IYBdhLWcg3wvT1a。因此,出于这个原因,我会暂时不选定它。 - mrmillsy

0

我遇到的问题是,通过 Me.GetType() 的字段集合进行迭代时,未返回“TestEvent”字段。我进行了进一步挖掘并意识到这是因为该事件在“代码后台”类中声明,例如myPageName.aspx.vb,然而,在运行时,此代码是从继承的“设计”类,例如myPageName.aspx中调用的。

这篇博客文章指出,即使使用了BindingFlags.FlattenHierarchy.GetType.GetField() 也不会从继承类返回私有静态字段:https://web.archive.org/web/20131213074318/http://bobpowell.net/eventsubscribers.aspx

因此,解决方案是使用Me.GetType.BaseType.GetField("TestEvent"),然后按照Tejas Sharma所描述的技术进行操作。这种技术的VB.NET示例在此答案中提供:如何将原始对象的事件附加到深度复制的克隆体

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接