【问题标题】:How to define events and properties in a decorator如何在装饰器中定义事件和属性
【发布时间】:2016-12-17 18:38:04
【问题描述】:

我定义了一个接口,它有一个事件和一个如下定义的属性。

public interface IMyInterface
{
    event EventHandler SomeEvent;
    string GetName();
    string IpAddress { get; set; }
}

然后我创建了一个类并使用它,一切正常。

现在我想使用装饰器扩展这个类。 我不确定如何处理该事件。对于属性我想我很清楚,只是想要确认

我定义了装饰器类如下。

public class LoggerDecorator : IMyInterface
{
    private readonly IMyInterface _MyInterface;
    private readonly ILog _MyLog;
    public LoggerDecorator(IMyInterface myInterface, ILog myLog)
    {
        if (myInterface == null)
            throw new ArgumentNullException("IMyInterface is null");
        _MyInterface = myInterface;

        if (myLog == null)
            throw new ArgumentNullException("ILog instance is null");
        _MyLog = myLog;

    }

    public string GetName()
    {
        // If needed I can use log here
        _MyLog.Info("GetName method is called.");
        return _MyInterface.GetName();
    }

    // Is this the way to set properties?
    public string IpAddress
    {
        get
        {
            return _MyInterface.IpAddress;
        }

        set
        {
            // If needed I can use log here
            _MyLog.Info("IpAddress is set.");
            _MyInterface.IpAddress = value;
        }
    }


    // But How to handle this evetn?? Please help. I am not clear about this.
    public event EventHandler SomeEvent;

}

【问题讨论】:

    标签: c# design-patterns decorator


    【解决方案1】:

    您可以使用addremove 将事件的订阅和取消订阅转发到正在装饰的元素。这样,如果你订阅了LoggerDecorator.SomeEvent,你实际上订阅了内部的IMyInterface.SomeEvent

    在你的情况下,它应该是这样的:

    public class LoggerDecorator : IMyInterface
    {
        (...)
    
        public event EventHandler SomeEvent
        {
            add => _MyInterface.SomeEvent += value;
            remove => _MyInterface.SomeEvent -= value;
        }
    }
    

    【讨论】:

      【解决方案2】:

      你不应该处理这个事件,你可以提出这个事件:

      喜欢:

      if(SomeEvent != null)
          SomeEvent(this, EventArgs.Empty);
      

      在 C# 6.0 中

      SomeEvent?.Invoke(this, EventArgs.Empty);
      

      【讨论】:

      • 好的,我想我明白了。让我试试。
      • 定义事件时。其他对象可以注册到它。因此,您的对象可以在不“知道”/限制接收者类的情况下进行“回调”。这样您就可以重用可以通知/调用方法的类。
      【解决方案3】:

      好的,我想我得到了答案。

      以下内容进入ctor。

              _MyInterface.SomeEvent += _MyInterface_SomeEvent;
      

      事件处理方法如下。

          private void _MyInterface_SomeEvent(object sender, EventArgs e)
          {
              var someEvent = SomeEvent;
              if (someEvent != null)
              {
                  someEvent(this, e);
              }
          }
      

      完整的实现如下。

      public class LoggerDecorator : IMyInterface
      {
          private readonly IMyInterface _MyInterface;
          private readonly ILog _MyLog;
          public LoggerDecorator(IMyInterface myInterface, ILog myLog)
          {
              if (myInterface == null)
                  throw new ArgumentNullException("IMyInterface is null");
              _MyInterface = myInterface;
      
              if (myLog == null)
                  throw new ArgumentNullException("ILog instance is null");
              _MyLog = myLog;
      
              // This is change 1.
              _MyInterface.SomeEvent += _MyInterface_SomeEvent;
          }
      
          // This is change 2
          private void _MyInterface_SomeEvent(object sender, EventArgs e)
          {
              var someEvent = SomeEvent;
              if (someEvent != null)
              {
                  someEvent(this, e);
              }
          }
      
          public string GetName()
          {
              // If needed I can use log here
              _MyLog.Info("GetName method is called.");
              return _MyInterface.GetName();
          }
      
          // Is this the way to set properties?
          public string IpAddress
          {
              get
              {
                  return _MyInterface.IpAddress;
              }
      
              set
              {
                  // If needed I can use log here
                  _MyLog.Info("IpAddress is set.");
                  _MyInterface.IpAddress = value;
              }
          }
      
      
          public event EventHandler SomeEvent;
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-31
        • 2015-10-23
        • 1970-01-01
        • 2018-07-20
        • 2018-11-21
        • 2012-06-02
        • 2019-03-20
        • 2021-09-05
        相关资源
        最近更新 更多