只处理初始化的对象?

Only dispose of initialized objects?

我有一个 API 包装器,它具有一系列在首次使用时初始化的属性。当 class 的 Disposed 方法被调用时,它会处理它存储的所有其他 classes。然而,很有可能只有一两个其他 classes 被初始化了。如果这些 classes 还没有被初始化,Dispose 方法实际上最终会初始化它们并处理它们。这需要大量资源和时间,但我想不出补救方法。

这是 class。

public class SalesForceApi : ISalesForce, IDisposable
{
    public Logger Logger = LogManager.GetCurrentClassLogger();

    private IAccounts _accounts;
    private IAttachments _attachments;
    private ICases _cases;
    private IContacts _contacts;
    private IGroups _groups;
    private IRecordTypes _recordTypes;
    private IUsers _users;

    public IAccounts Accounts => _accounts ?? (_accounts = new Accounts());

    public IAttachments Attachments => _attachments ?? (_attachments = new Attachments());
    public ICases Cases => _cases ?? (_cases = new Cases());
    public IContacts Contacts => _contacts ?? (_contacts = new Contacts());
    public IGroups Groups => _groups ?? (_groups = new Groups());
    public IRecordTypes RecordTypes => _recordTypes ?? (_recordTypes = new RecordTypes());
    public IUsers Users => _users ?? (_users = new Users());

    public SalesForceApi()
    {

    }

    public void Dispose()
    {
        Logger.Trace("Disposing of Acccounts...");
        Accounts.Dispose();
        Logger.Trace("Disposing of Attachments...");
        Attachments.Dispose();
        Logger.Trace("Disposing of Cases...");
        Cases.Dispose();
        Logger.Trace("Disposing of Contacts...");
        Contacts.Dispose();
        Logger.Trace("Disposing of Groups...");
        Groups.Dispose();
        Logger.Trace("Disposing of RecordTypes...");
        RecordTypes.Dispose();
        Logger.Trace("Disposing of Users...");
        Users.Dispose();
    }
}

结果日志如下所示:

SalesForceApi_v1.SalesForceApi::Disposing of Acccounts...
SalesForceApi_v1.Requests.RequestBase::Logging into SalesForce...
SalesForceApi_v1.Requests.RequestBase::SalesForce login successful!
SalesForceApi_v1.Requests.RequestBase::Logging out of SalesForce.
SalesForceApi_v1.SalesForceApi::Disposing of Attachments...
SalesForceApi_v1.Requests.RequestBase::Logging into SalesForce...
SalesForceApi_v1.Requests.RequestBase::SalesForce login successful!
SalesForceApi_v1.Requests.RequestBase::Logging out of SalesForce.
SalesForceApi_v1.SalesForceApi::Disposing of Cases...
SalesForceApi_v1.Requests.RequestBase::Logging into SalesForce...
SalesForceApi_v1.Requests.RequestBase::SalesForce login successful!
SalesForceApi_v1.Requests.RequestBase::Logging out of SalesForce.
SalesForceApi_v1.SalesForceApi::Disposing of Contacts...
SalesForceApi_v1.Requests.RequestBase::Logging out of SalesForce.
SalesForceApi_v1.SalesForceApi::Disposing of Groups...
SalesForceApi_v1.Requests.RequestBase::Logging into SalesForce...
SalesForceApi_v1.Requests.RequestBase::SalesForce login successful!
SalesForceApi_v1.Requests.RequestBase::Logging out of SalesForce.
SalesForceApi_v1.SalesForceApi::Disposing of RecordTypes...
SalesForceApi_v1.Requests.RequestBase::Logging into SalesForce...
SalesForceApi_v1.Requests.RequestBase::SalesForce login successful!
SalesForceApi_v1.Requests.RequestBase::Logging out of SalesForce.
SalesForceApi_v1.SalesForceApi::Disposing of Users...
SalesForceApi_v1.Requests.RequestBase::Logging into SalesForce...
SalesForceApi_v1.Requests.RequestBase::SalesForce login successful!
SalesForceApi_v1.Requests.RequestBase::Logging out of SalesForce. 

配置时,不要调用lazy-init的方法;测试并处理私有成员变量(_accounts 等)。

不要在 Dispose 方法中使用属性,使用私有字段。

public void Dispose()
{
    Logger.Trace("Disposing of Acccounts...");
    if(_accounts != null) _accounts.Dispose();
    Logger.Trace("Disposing of Attachments...");
    if(_attachments != null) _attachments.Dispose();
    // ...
}

您可以将您的处置包装在私有成员空检查中。由于您是延迟加载,因此调用 Property.Dispose() 实际上会创建 class 的实例,只是为了处理它。我还喜欢在处理后将我的成员设置为 null,这样如果我再次尝试访问它,它就会抛出 NullReferenceException。

public void Dispose()
{
    if (_accounts != null) 
    {
        Logger.Trace("Disposing of Acccounts...");
        Accounts.Dispose();
        // or
        // _accounts.Dispose();
        // _accounts = null;
    }
    if (_attachments != null) 
    {
        Logger.Trace("Disposing of Attachments...");
        Attachments.Dispose();
        // or
        // _attachments.Dispose();
        // _attachments = null;
    }
    if (_cases != null) 
    {
        Logger.Trace("Disposing of Cases...");
        Cases.Dispose();
        // or
        // _cases.Dispose();
        // _cases= null;
    }
    if (_contacts != null) 
    {
        Logger.Trace("Disposing of Contacts...");
        Contacts.Dispose();
        // or
        // _contacts.Dispose();
        // _contacts = null;
    }
    if (_groups != null) 
    {
        Logger.Trace("Disposing of Groups...");
        Groups.Dispose();
        // or
        // _groups.Dispose();
        // _groups = null;
    }
    if (_recordTypes != null) 
    {
        Logger.Trace("Disposing of RecordTypes...");
        RecordTypes.Dispose();
        // or
        // _recordTypes.Dispose();
        // _recordTypes = null;
    }
    if (_users!= null) 
    {
        Logger.Trace("Disposing of Users...");
        Users.Dispose();
        // or
        // _users.Dispose();
        // _users= null;
    }
}