c# - 订阅/取消订阅(添加/删除)扩展方法内的事件

标签 c# events c#-4.0 extension-methods presenter-first

我想创建一个流畅的扩展方法来订阅(以及不太重要的是取消订阅)事件。这是一个使用 .RespondBy(Method) 代替 += new Eventhandler(Method)

的扩展

我想这样做:object.WhenSomethingChanges.RespondBy(DoingThisOtherThing);

而不是这样:object.WhenSomethingChanges += new EventHandler(DoingThisOtherThing);

我做了很多谷歌搜索,虽然我没有完全掌握复杂的细节,但我现在明白这与您是否访问本地领域或公共(public)事件有关。

话虽如此,我只是对“如何”做到这一点感兴趣,而不关心“为什么”我的第一次尝试没有成功。如果解决方法失败,至少明确的“你永远不能这样做......根本,永远。”也会是有用的信息...

<强> CommuncationsStatusPresenter (Image)

Image of attempted usage, does not compile

CommuncationsStatusPresenter(代码)

using System;
using InspectionStation.Models;
using InspectionStation.Views;
using MachineControl.OPC;

namespace InspectionStation.Presenters
{
    public class CommuncationsStatusPresenter
    {
        // Fields
        private ICommunicationsModel m_model;
        private ICommunicationsView m_view;

        // Constructor
        public CommuncationsStatusPresenter
            (ICommunicationsModel p_model, ICommunicationsView p_view)
        {
            m_model = p_model;
            m_view = p_view;
            HookEvents();
        }
        private void HookEvents()
        {
            m_model
                .When_Communications_Pulses_Heartbeat
                .RespondBy(Setting_the_state_of_an_Indicator);
        }

        // Eventhandler
        void Setting_the_state_of_an_Indicator(Tag sender, EventArgs e)
        {
            bool State = sender.BooleanValue;
            m_view.Set_Communications_Status_Indicator = State;
        }
    }
}

回复

using System;

namespace Common.Extensions
{
    public static partial class ExtensionMethods
    {
        public static
            void RespondBy<TSender, TEventArgs>(this
            GenericEventHandler<TSender, TEventArgs> p_event,
            GenericEventHandler<TSender, TEventArgs> p_handler
            ) where TEventArgs : EventArgs
        {
            p_event += new GenericEventHandler<TSender, TEventArgs>(p_handler);
        }
    }
}

GenericEventHandler

using System;

namespace Common
{
    [SerializableAttribute]
    public delegate void GenericEventHandler<TSender, TEventArgs>
        (TSender sender, TEventArgs e)
        where TEventArgs : EventArgs;
}

ICommunicationsModel

using System;
using Common;
using MachineControl.OPC;

namespace InspectionStation.Models
{
    public interface ICommunicationsModel
    {
        event GenericEventHandler<Tag, EventArgs>
            When_Communications_Pulses_Heartbeat;
    }
}

ICommunicationsView

namespace InspectionStation.Views
{
    public interface ICommunicationsView
    {
        bool Set_Communications_Status_Indicator { set; }
    }
}

最佳答案

因为 C# 编译器严格要求在类外部使用的事件后面必须跟有 +=-=,因此附加和分离处理程序的命令,将无法在类外部扩展和使用它。

但是,如果您愿意在类本身上构建更具体的方法,例如:

object.RespondWhenSomethingChangesBy(DoingThisOtherThing);

然后您可以在该方法内部利用扩展方法,因为该类定义了事件。我知道这意味着您将为事件构建大量样板代码,但如果这是您真正想要的,那么上述内容可能会比以下内容更加简化:

object.WhenSomethingChanges.RespondBy(DoingThisOtherThing);

我完全理解你在这里的立场,并希望微软选择允许 future 延长事件(我可以想到一些我会使用它的有趣原因),但在那之前我想我们只会有解决它。老实说,我相信有一些非常充分的理由它一开始就没有实现,微软在考虑这些事情方面做得非常好。

关于c# - 订阅/取消订阅(添加/删除)扩展方法内的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15962145/

相关文章:

.net - 何时将代码分离到新程序集(DLL)中

c# - 常量不能标记为静态

c# - 检查空格 Regex C#

c# - 使用 C# 将半径添加到经度和纬度

Java处理自定义事件

c# - 来自非常大的 int C# 的模数

c# - 使用静态方法还是实例化类?

javascript - Meteor:实例化一个Session,没有点击事件

java - 使用Spring应用事件发布有什么优势?

c# - .NET 有链接器吗?