2

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

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

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

我做了一堆谷歌搜索,虽然我没有完全掌握错综复杂的细节,但我现在明白这与你是访问本地领域还是公共活动有关。

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

通信状态演示者(图片)

尝试使用的图像,无法编译

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);
        }
    }
}

通用事件处理程序

using System;

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

通信模型

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; }
    }
}
4

2 回答 2

1

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

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

object.RespondWhenSomethingChangesBy(DoingThisOtherThing);

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

object.WhenSomethingChanges.RespondBy(DoingThisOtherThing);

我完全理解你在这里的立场,并希望微软选择允许将来扩展事件(我能想到一些我会使用它的有趣原因),但在那之前我想我们只需要解决它。老实说,我相信有一些很好的理由首先没有实施它,微软在考虑这些事情方面做得很好。

于 2013-04-12T03:42:35.580 回答
1

鉴于Michael Perrenoud的回答,我已决定将以下内容作为我的模式的一部分......

    public class CommuncationsStatusPresenter
    {
        ...

        private void HookEvents()
        {
            m_model.
                When_Communications_Pulses_Heartbeat += new EventHandler<Tag, EventArgs>(
                Set_the_state_of_an_Indicator);
        }

        // Eventhandler
        void Set_the_state_of_an_Indicator(Tag sender, EventArgs e)
        {
            ...
        }
    }
}

没什么特别的......只是基于新行的一致自动格式化,但似乎是目前最好的解决方案(即,我几乎可以大声阅读代码以快速确定其意图,而无需求助于广泛的注释描述)。

注意:我将 long 重命名为GenericEventHandlersimple EventHandler,因为不需要特殊名称。

于 2013-04-12T04:10:57.273 回答