简体   繁体   中英

How to safely dispose an instance of a client returned from a singleton?

Given I have the following code which is provided as a singleton lifetime service through .net core, how can I safely dispose of a client (it does implement IDisposable) and the create a new one. I'm concerned once I call Dispose the old client, it will be removed and in the meantime any callers that retrieved the client will be pointing at a client that is now disposed.

public class MyClientFactory: IMyClientFactory
{
    private Client { get; set; }

    public async Task<IMyClient> GetClient()
    {
        if (this.Client != null && DoSomeChecksToSeeIfValid())
        {
            return this.Client;
        }
        else
        {
            this.Client?.Dispose();

            this.Client = new MyClient(await DoSomethingToGetNewCredentials());

            return this.Client;
        }
    }
}

If you want to control the lifetime it's best not to return an instance of the object. But if this doesn't suit you you can use the event model.

public interface IMyClientManager
{
     void Do(Action<MyClient> action);
}
public interface IMyClient : IDisposable
{
    
}
public sealed class MyClient: IMyClient
{
    public delegate void DisposeHandle();

    public event DisposeHandle DisposeEvent;

    private bool _isDispose;
    public void Dispose()
    {
        if (!_isDispose)
            DisposeEvent?.Invoke();
        _isDispose = true;
    }
}

public class MyClientManager : IMyClientManager
{
    private MyClient Client { get; set; }
    private object _sync = new object();
    private bool DoSomeChecksToSeeIfValid()
    {
        return this.Client != null;
    }

    public void Do(Action<MyClient> action)
    {
        // you can  create connection pull
        while (!DoSomeChecksToSeeIfValid())
        {
            InitClient();
            //todo: connect or setup
        }

        action.Invoke(this.Client);
    }

    private void InitClient()
    {
        if (this.Client == null)
        {
            lock (_sync)
            {
                this.Client ??= new MyClient();
                this.Client.DisposeEvent += Client_DisposeEvent;
            }

        }
    }

    public MyClient Create()
    {
        // you can  create connection pull
        while (!DoSomeChecksToSeeIfValid())
        {
            InitClient();
            
        }

        return this.Client;
    }

    private void Client_DisposeEvent()
    {
        lock (_sync)
        {
            this.Client.DisposeEvent-= Client_DisposeEvent;
            this.Client = null;
        }

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM