C# 通用事件处理 - 链接/代理

标签 c# events generics event-handling

我试图想出一种通用方法来拦截 C# 事件进行处理(例如日志记录、过滤、异步分发等),然后再将事件传递回其原始使用者。

举个例子,在正常的流程中你会遇到

class EventProducer
{
    public event EventHandler<int> OnEvent;

    internal void FireEvent()
    {
        if (OnEvent != null)
            OnEvent(this, 1);
    }
}

class EventConsumer
{
    public EventConsumer(EventProducer producer)
    {
        producer.OnEvent += eventHandler;
    }

    public void eventHandler(object sender, int e)
    {
        Debug.WriteLine("Consumed " + e);
    }

}

就我而言,我想在两者之间插入一个额外的步骤..类似于

//event consumer
class EventConsumer
{
    //use this to handle one particular event (EventProducer.OnEvent)
    InterceptEventHandler<int> EventHandler;

    public EventConsumer(EventProducer producer)
    {
        //just one line of code to insert an event handler to do what I need
        //but whoops - cant refer to OnEvent outside of the producer
        EventHandler = new InterceptEventHandler<int>(producer.OnEvent, eventHandler);
    }

    public void eventHandler(object sender, int e)
    {
        Debug.WriteLine("Consumed " + e);
    }
}

//intercepts events, does something with them, then forwards them to original consumer
class InterceptEventHandler<T>
{
    public EventHandler<T> Callback;

    public InterceptEventHandler(EventHandler<T> eventHook, EventHandler<T> callback)
    {
        //save callback
        Callback = callback;

        //subscribe ourselves to the specified event
        eventHook += interceptHandler;
    }

    public void interceptHandler(object sender, T e)
    {
        //do something with the event here
        Debug.WriteLine("Intercepted " + e.ToString());

        //then pass callback back to original consumer
        Callback(sender, e);
    }
}

问题(如上所述)是代码无法编译,因为事件本身无法从生产者类外部访问。我理解这是因为事件处理是作为私有(private)类实现的,所以看不到任何明显的解决方法。

是否有任何方法可以拦截和链接事件,使我能够在生成器类中保留标准事件语法?

我意识到我可以放弃事件,而只使用我自己的等效生产者/消费者代码,但我会失去事件的正常好处(例如,更具可读性/可维护性、正确的语法突出显示/自动完成等)

编辑 - 我还尝试摆弄 MulticastDelegate 类,但是当我编译代码时,我无法订阅事件(实际上 OnEvent 始终为空)。

最佳答案

而不是接受EventHandler这当然不是事件类型,接受 Action<EventHandler>它代表订阅事件的操作:

public class InterceptEventHandler
{
    public static void Attach<T>(Action<EventHandler<T>> eventHook,
        EventHandler<T> callback)
    {
        eventHook((sender, args) =>
        {
            doStuffOnFire(sender, args);
            callback(sender, args);
        });
    }
    private static void doStuffOnFire<T>(object sender, T e)
    {
        //...
    }
}

然后你可以这样调用它:

public EventConsumer(EventProducer producer)
{
    InterceptEventHandler.Attach<int>(
        handler => producer.OnEvent += handler,
        eventHandler);
}

关于C# 通用事件处理 - 链接/代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24494116/

相关文章:

c# - SQL Server 2008 的 Java 替代方案 - 紧凑

android - 如何到达 ListView 的底部,加载更多项目

c# - .Net Microframework 中的自定义事件

c# - 我如何将 'ping' 排序为 SMTP 服务器,以便检查帐户/密码是否有效?

c# - 自定义方法 "GetControlsOfType"似乎在上升控制结构以及下降

c# - 连接到本地 nCache

java - 如何使用 GWT EventBus

c# - 使用泛型调用重载函数

generics - 返回两个值中的第一个的通用方法

java - 获取泛型类型的类的类型?