迫害IDisposable

时间:2017-04-05 10:52:31

标签: c# garbage-collection

我真的无法想到一个标题,可以用几个词来形容我需要的更多细节。   最终我的想法是,我使用自定义实现向Azure Service Bus发送消息。此实现包含在NuGet包中,并且我尝试添加一些额外的逻辑,这些逻辑将消息保存到数据库,这是QA自动化目的所需的。这里棘手的部分是我希望NuGet包保持不变,并且所有其他逻辑都被包裹起来#34;周围。   所以包本身有很多sealed类和internal接口,但我想我已经设法提取了我需要的链。   首先,我有这个接口,用于从所有类发布消息到服务总线:

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接口之一。然后我有一个实现这个接口的抽象类:

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

所以最后我有sealed类继承了抽象MessageBusBase

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

有了这张图片我真的很感激,如果有人可以解释我在抽象类中析构函数的目的是什么以及为什么我们需要它。我花了一些时间阅读关于何时以及为什么要使用析构函数的结论,而我得出的结论是,实际上我们很可能并不需要它。但是AzureMessageBusAzure的实际调用是IMessage,我们在SendMessageAsync方法中使用的Google.ProtocolBuffers界面来自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

return (IMessageBus) new AzureMessageBus(..) 返回AzureMessageBus的实例,如下所示:

IMessageBus

所以基本上都是这样,从我的新班级我调用AzureMessageBusWithLogging方法的原始实现,但因为我需要在我的新班级中实现 public void Dispose() { throw new NotImplementedException(); } { {1}}我被迫添加:

GC

但我真的不知道该怎么做,如果我真的需要做点什么的话。而且我真的很感谢为什么我们需要这个(从我的观点来看很复杂)AzureMessageBus的实现以及如果以任何方式处理我的新类可能会影响现有的(&(objectCategory=group)(memberOf:1.2.840.113556.1.4.1941:=CN=GroupOne,OU=Security Groups,OU=Groups,DC=YOURDOMAIN,DC=NET)) 我在新课堂上使用了它的实例。

1 个答案:

答案 0 :(得分:2)

  1. 您不需要析构函数,因为您不需要保留任何需要释放的直接非托管资源。如果只包装一些IDisposable对象 - 只需实现Dispose而不使用析构函数。如果这些对象确实拥有一些非托管资源 - 它们将拥有自己的析构函数。

  2. 您不需要MessageBusBase : IMessageBus, IDisposable,因为IMessageBus已包含IDisposable。虽然如果你这样做 - 没有任何伤害

  3. AzureMessageBusWithLogging中,您将其他IMessageBus messageBus换行。所以在Dispose - 处置messageBus

  4. 所以一般来说:如果你包装一些一次性对象 - 你的类也应该实现IDisposable并将所有这些包装好的对象放在它自己的Dispose中,就像你在{{{ 1}}。