繁体   English   中英

如何更改事件分配的方法?

[英]How can I change a method assigned on an event?

我正在获取具有某个属性的所有事件,并且我想修改这些事件,添加对另一个方法的调用。

var type = GetType();
var events = type.GetEvents().Where(e => e.GetCustomAttributes(typeof(ExecuteAttribute), false).Length > 0);

foreach (var e in events)
{
    var fi = type.GetField(e.Name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);
    var d = (Delegate)fi.GetValue(this);
    var methods = d.GetInvocationList();
    foreach (var m in methods)
    {
        var args = e.EventHandlerType.GetMethod("Invoke").GetParameters().Select(p => Expression.Parameter(p.ParameterType, "p")).ToArray();
        var body = m.Method.GetMethodBody();

        /**

        TODO:

        Create a new method with the body of the previous
        and add a call to another method

        Remove current method
        Add the new created method

        **/
    }
}

我想要的基本上是上面评论的内容。 “修改”事件的订阅方法。 我想我不能订阅它,因为我需要传递方法传递给大处理程序的参数(新方法)。

基于这个问题的另一个例子。 我想转换这个:

var e += (x) =>
{
    var y = x;
};

对于这样的事情:

var e += (x) =>
{
    var y = x;

    BigHandler(x); // injected code
};

或这个:

var e += (x) => // new method
{
    previousE(x); // previous method

    BigHandler(x); // additional code
}

我该怎么做?


更大的目标:

我需要在事件被触发时“检测”并调用方法。 我还需要发送它正在使用的参数。

所以我可以做类似的事情:

public delegate void OnPostSaved(Post p);
[Execute]
public event OnPostSaved PostSaved;

public void Save()
{
    /* save stuff */
    // assume that there is already an event subscribed
    PostSaved(post);
}

然后在我的处理程序方法中,我可以检查来自XYZ的事件是否被触发,检查触发了哪个事件,检索参数并执行某些操作。 例如:

public void BigHandler(string eventName, params object[] p)
{
    if (eventName == "PostSaved")
    {
        var post = p[0] as Post;
        MessageBoard.Save("User posted on the blog: " + post.Content);
    }
}

我知道可以使用PostSharp实现,但我无法使用它。 我需要另一个解决方案


有关


更新2010-09-27我找不到解决方案既没有更多的信息,我仍然需要帮助。 增加了+150赏金。

如果你只是添加一个电话,那很简单 - 你不需要获取所有订阅的代表或类似的东西; 只需订阅反射:

var type = GetType();
// Note the small change here to make the filter slightly simpler
var events = type.GetEvents()
                 .Where(e => e.IsDefined(typeof(ExecuteAttribute), false));

foreach (var e in events)
{
    // "handler" is the event handler you want to add
    e.AddEventHandler(this, handler);
}

现在,我做了你想做什么的假设-即每一次的事件引发时间打电话给你的方法。 这与每次调用事件处理程序时调用您的方法不同,这是您的原始代码所要完成的。 这是非常困难......但你真的需要它吗?

(如果你能在这里提供更多有关更大目标的信息,那真的会有所帮助。)

请注意, 无论事件是如何实现的,我在这里提供的代码都应该有效 - 它不依赖于它是类似字段的事件。

编辑:好的,这是一个完整的示例,显示如何将普通的EventHandler委托添加到与正常事件模式匹配的任何事件:

using System;
using System.Reflection;

class CustomEventArgs : EventArgs {}

delegate void CustomEventHandler(object sender, CustomEventArgs e);

class Publisher
{
    public event EventHandler PlainEvent;
    public event EventHandler<CustomEventArgs> GenericEvent;
    public event CustomEventHandler CustomEvent;

    public void RaiseEvents()
    {
        PlainEvent(this, new EventArgs());
        GenericEvent(this, new CustomEventArgs());
        CustomEvent(this, new CustomEventArgs());
    }
}

class Test
{
    static void Main()
    {
        Publisher p = new Publisher();

        Type type = typeof(Publisher);

        foreach (EventInfo eventInfo in type.GetEvents())
        {
            string name = eventInfo.Name;
            EventHandler handler = (s, args) => ReportEvent(name, s, args);
            // Make a delegate of exactly the right type
            Delegate realHandler = Delegate.CreateDelegate(
                 eventInfo.EventHandlerType, handler.Target, handler.Method);
            eventInfo.AddEventHandler(p, realHandler);
        }

        p.RaiseEvents();
    }

    static void ReportEvent(string name, object sender, EventArgs args)
    {
        Console.WriteLine("Event {0} name raised with args type {1}",
                          name, args.GetType());
    }
}

注意我们如何构造所需的确切类型的委托 - 但我们知道我们可以通过兼容的方法来做到这一点,只要一切都遵循正常的事件模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM