【问题标题】:How to implement an interface returns IAsyncResult with empty method body如何实现接口返回带有空方法体的 IAsyncResult
【发布时间】:2019-06-17 22:13:58
【问题描述】:

如果我想继承ChannelBase,WCF 需要我实现类似IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 的方法。由于通道打开时我无事可做,因此我宁愿将该方法主体留空。在那些空方法中我应该以IAsyncResult 的形式返回什么?

【问题讨论】:

    标签: c# .net wcf asynchronous


    【解决方案1】:

    通过将 IAsyncResult 实现添加为已完成的异步结果来解决

    internal class CompletedAsyncResult : IAsyncResult
    {
        public CompletedAsyncResult(object state)
        {
            this.AsyncState = state;
        }
    
        public object AsyncState { get; set; }
    
        public WaitHandle AsyncWaitHandle => new ManualResetEvent(true);
    
        public bool CompletedSynchronously => true;
    
        public bool IsCompleted => true;
    }
    

    和使用一样

    protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
    {
        var result = new CompletedAsyncResult(state);
        callback?.Invoke(result);
        return result;
    }
    

    【讨论】:

      【解决方案2】:

      根据经验,您根本不应该有空方法。如果ChannelBase 有一个你不需要的抽象方法,你应该提供一个合理的覆盖,即使你现在不需要,或者从它抛出一个NotSupportedException,异常消息解释了为什么这个方法不支持:

      public override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 
      {
          throw new NotSupportedException("OnBeginOpen is not supported because...");
      }
      

      【讨论】:

      • 感谢您的建议。我的问题实际上是关于如何提供什么都不做的合理覆盖,而不是字面上的“空体”。
      • 您可以简单地返回null,但这为空引用异常提供了可能性——在这种情况下,最好在源方法中抛出NotSupportedException。关键是,如果不实际实现某些东西,就不可能有一个明智的覆盖——因为你不想或不能实现这个方法,所以明智的做法是抛出一个异常。
      • 但是有可能什么都不做才是正确的选择。就像我的 Open 方法一样,它是一个空方法,因为它不应该做任何事情。所有初始化工作都在ChannelFactory 中完成。现在 WCF 要求我提供一个OnBeginOpen 方法来支持异步打开通道。我唯一需要OnBeginOpen 做的就是什么都不做,这应该是一个有效的选择。我不能只抛出像NotSupportedException 这样的东西,因为它实际上是受支持的,而返回null 会带来NullReferenceException 的风险。我只需要像Task.CompletedTask 这样的东西。
      • 如果您的Open 方法是无操作的,而您的OnBeginOpen 方法是无操作的,也许您根本不应该继承该基类。我不知道您要完成什么,因此如果没有更多详细信息,我真的无法提供更多帮助。在我看来,这现在像是一个 XYProblem。
      • 很抱歉给您带来了困惑。我正在为 WCF 编写自定义传输通道。当你继承ChannelBase 时,你将不得不实现它提供的所有抽象方法,其中一些应该什么都不做。如果该方法是同步方法,我可以将主体留空。如果它是基于 TPL 的,我会返回 Task.CompletedTask。当是 APM 时,我不知道什么是最好的解决方案。
      猜你喜欢
      • 2017-03-04
      • 2015-01-01
      • 1970-01-01
      • 2012-08-08
      • 1970-01-01
      • 2012-04-03
      • 2014-06-15
      • 2011-05-16
      • 2011-06-22
      相关资源
      最近更新 更多