使用反射添加事件处理程序

时间:2008-12-16 21:24:40

标签: c# asp.net events user-controls

我通过使用LoadControl和Controls.Add向页面添加动态控件。我需要以某种方式将这个加载的控件的Init和Load事件处理程序包装到我的代码中。所以它应该是这样的事件顺序 SomeMyCode() - > Control.Init() - > AnotherMyCode()和Load SomeMyCode() - >相同Control.Load() - > AnotherMyCode()的。
我的想法是获取Init和Load事件的控制列表的事件处理程序,并添加我应该运行的代码的第一个和最后一个事件处理程序。但我无法弄清楚如何做到这一点。

2 个答案:

答案 0 :(得分:1)

无法在已订阅事件的其他处理程序前强行注入事件处理程序。如果您需要首先调用方法A,那么您需要首先订阅A.


重新发表你的评论,这真是令人难以置信的hacky。首先,您甚至不能依赖具有委托字段支持者的事件;它可以是EventHandlerList或其他 - 它不会暴露出方便的钩子而不能逆转移除。

其次(更重要的是),它打破了封装的每一条规则。

通常,如果您想成为第一个,最佳方法是覆盖OnFoo()方法。第二好的是先订阅。

答案 1 :(得分:0)

以下是工作解决方案的草稿:

    protected void Page_Load(object sender, EventArgs e)
    {
        Control ctrl = this.LoadControl("WebUserControl1.ascx");
        PropertyInfo propertyInfo = typeof(Control).GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
        EventHandlerList eventHandlerList = propertyInfo.GetValue(ctrl, new object[]{}) as EventHandlerList;
        FieldInfo fieldInfo = typeof(Control).GetField("EventLoad", BindingFlags.NonPublic | BindingFlags.Static);

        if(fieldInfo == null)
            return;

        object eventKey = fieldInfo.GetValue(ctrl);
        Delegate eventHandler = eventHandlerList[eventKey] as Delegate;

        foreach(EventHandler item in eventHandler.GetInvocationList()) {
            ctrl.Load -= item;
        }

        ctrl.Load += ctrl_Load;
        foreach (EventHandler item in eventHandler.GetInvocationList()){
            ctrl.Load += item;
        }
        ctrl.Load += ctrl_Load;

        this.Controls.Add(ctrl);
    }

    void ctrl_Load(object sender, EventArgs e)
    {
        //throw new NotImplementedException();
    }
}