【问题标题】:Raising event via reflection using webforms with codebehind使用带有代码的 Web 表单通过反射引发事件
【发布时间】:2014-12-17 14:43:22
【问题描述】:

我意识到有许多问题涉及通过反射引发事件,但是我无法找到以下问题的答案 [我怀疑答案是否定的]:

给定一个事件的“标准”声明,有没有办法通过引用字符串文字来引发事件。

例如伪代码:

Dim eventName As String = "TestEvent"
RaiseEvent eventName

显然这行不通。

我可以通过

获取事件处理程序/多播委托的类型
Me.GetType.GetEvent("TestEvent").GetAddMethod.GetParameters(0).Name
// "TestEventEventHandler

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

这类似于这个问题:How can I get an actual EventHandler delegate instance from an event in VB.NET?

但是,我在这里专门研究从字符串引发事件。

编辑:

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

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

第二点不同,虽然与最终答案无关,但在 c# 中您可以直接引用事件处理程序 MulticastDelegate,但在 vb.net 中您不能 - 或者至少,您不能这样做必须使用智能感知不支持的未记录功能,如:How can I get an actual EventHandler delegate instance from an event in VB.NET?

【问题讨论】:

  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 好的,谢谢。不过,我在这里有一个问题 - 这具体是一个 vb.net/asp.net 问题,因为 c#/winforms 的解决方案与 vb.net/webforms 的解决方案不同。我应该在标题中还是仅在问题中反映问题的这个必要元素?我觉得暗示这个问题是一个通用的“.net events via reflection”问题是一种误导。
  • 现在我已经编辑了问题以反映 webforms/vb.net 带来的困难
  • 重新阅读您链接到的主题后,我已经更新了标题。你觉得这样更合适吗?
  • 好多了。您已将元数据转化为数据。

标签: asp.net .net vb.net events reflection


【解决方案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!");
    }
}

【讨论】:

  • 谢谢,这表面上是答案,所以我会赞成,但我认为它没有准确地考虑到网络表单的概念,这就是使这个问题与其他类似答案不同的原因,比如stackoverflow.com/questions/198543/…。出于这个原因,我将不打勾。
【解决方案2】:

我遇到的问题是遍历Me.GetType() 的字段集合没有返回“TestEvent”字段。我做了一些进一步的挖掘并意识到这是因为事件是在“代码背后”类中声明的,例如myPageName.aspx.vb,然而,在运行时,这个代码是从继承的“设计”类中调用的,例如我的页面名称.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 示例:How to Attach the Events of an Original Object to a Deep Copied Clone

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多