首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >冲击IDisposable

冲击IDisposable
EN

Stack Overflow用户
提问于 2017-04-05 10:52:31
回答 1查看 60关注 0票数 1

我真的想不出一个标题,它可以用几个词来描述我需要的更多细节。最终的想法是,我使用自定义实现向Azure Service Bus发送消息。这个实现被包装在一个NuGet包中,我试图添加一些额外的逻辑来将消息保存到QA自动化所需的数据库中。这里的棘手之处在于,我希望NuGet包保持不变,所有附加的逻辑都围绕着它“包装”。所以包本身有很多sealed类和internal接口,但是我想我已经成功地提取了我需要的链。首先,我有一个接口,用于从所有类将消息发布到服务总线:

代码语言:javascript
复制
public interface IMessageBus : IDisposable
{
    bool Send(IMessage command);

    bool Send(IMessage command, string trackingId);

    Task<bool> SendAsync(IMessage command);

    Task<bool> SendAsync(IMessage command, string trackingId);

    bool Publish(IMessage eventObj);

    bool Publish(IMessage eventObj, string trackingId);

    Task<bool> PublishAsync(IMessage eventObj);

    Task<bool> PublishAsync(IMessage eventObj, string trackingId);
}

它是包的一部分,但是为数不多的public接口之一。然后我有一个实现这个接口的抽象类:

代码语言:javascript
复制
public abstract class MessageBusBase : IMessageBus, IDisposable
{
    ~MessageBusBase()
    {
        this.Dispose(false);
    }

    #region Interface

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize((object)this);
    }

    protected abstract bool SendMessage(IMessage payload, string trackingId);

    protected abstract Task<bool> SendMessageAsync(IMessage payload, string trackingId);

    protected abstract void Dispose(bool disposing);
}

从这里开始,我开始失去实现背后的想法。既然IMessageBus已经实现了IDisposable,为什么抽象类应该再次实现它呢?Resharper也将其标记为不需要,但我已经学会了不要每次都信任Resharper

因此,在最后我有继承抽象MessageBusBaseMessageBusBase

代码语言:javascript
复制
public sealed class AzureMessageBus : MessageBusBase
{
    private bool isDisposed;

    #region MessageBusBase

    protected override void Dispose(bool disposing)
    {
        if (!disposing)
            return;
        this.isDisposed = true;
        foreach (IDisposable disposable in (IEnumerable<ISender>)this.senders.Values)
            disposable.Dispose();
    }
}

如果有人能解释一下抽象类中析构函数的用途以及我们为什么需要它,我会非常感激的。我花了一些时间阅读关于何时和为什么应该使用析构函数,我得出的结论是,实际上我们很可能不需要它。然而,在AzureMessageBus中是对Azure的实际调用,我们在SendMessageAsync方法中使用的IMessage接口也来自Google.ProtocolBuffers,也许这就是答案,但现在我只是猜测。这是我问题的第一部分。

第二部分是添加我的附加逻辑。为此,我创建了一个新类:

代码语言:javascript
复制
public class AzureMessageBusWithLogging : IMessageBus
{
    private IMessageBus messageBus;

    private IMessagingFactory messageFactory;

    public AzureMessageBusWithLogging(IMessagingFactory msgFactory)
    {
        this.messageFactory = msgFactory;

        if (messageFactory != null)
        {
            this.messageBus = this.messageFactory.CreateMessageBus();
        }
    }

    public Task<bool> SendAsync(IMessage command, string trackingId)
    {
        //Place for my additional logic
        return ((AzureMessageBus)messageBus).SendAsync(command, trackingId);
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }

    #region IMessageBus
}

其中this.messageFactory.CreateMessageBus();返回AzureMessageBus的一个实例,如下所示:

代码语言:javascript
复制
 return (IMessageBus) new AzureMessageBus(..)

基本上,从我的新类中,我调用了来自AzureMessageBus的方法的原始实现,但是由于我需要在我的新类AzureMessageBusWithLogging中实现IMessageBus,所以我不得不添加:

代码语言:javascript
复制
    public void Dispose()
    {
        throw new NotImplementedException();
    }

但我真的不知道该放什么进去,如果我真的需要做点什么。此外,我也很想解释一下为什么我们需要GC的实现(从我的角度来看很复杂),以及如果在我的新类中处理可能会以任何方式影响现有的AzureMessageBus,因为我在我的新类中使用了它的实例。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-05 11:02:30

  1. 您不需要析构函数,因为您不需要释放任何直接的非托管资源。如果您只是包装一些IDisposable对象-只需实现Dispose而不需要析构函数。如果这些对象持有一些非托管资源,它们将拥有自己的析构函数。
  2. 您不需要执行MessageBusBase : IMessageBus, IDisposable,因为IMessageBus已经包含了IDisposable。不过,如果你那样做-没有什么害处
  3. 在您的AzureMessageBusWithLogging中,您可以包装另一个IMessageBus messageBus。所以在Dispose中-处理那个messageBus

因此,通常情况下:如果您包装了一些一次性对象--您的类还应该实现IDisposable并在它自己的Dispose中释放所有包装的对象,就像在AzureMessageBus.Dispose中所做的那样。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43229082

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档