2

シングルトンを持つクラス「BaseClient」から継承し、継承されたクラスでも基本クラスシングルトンの基本メンバーの同じインスタンスを使用できるようにする方法を知りたいです。

public class BaseClient
{
    protected string _url;
    protected string _username;
    protected string _password;

    private static BaseClient _instance;
    private static readonly object padlock = new object();

    public static BaseClient Instance
    {
        get
        {
            lock (padlock)
            {
                if (_instance == null)
                {
                    _instance = new BaseClient(true);
                }
                return _instance;
            }
        }
    }

    public void SetInfo(string url, string username, string password)
    {
        _url = url;
        _username = username;
        _password = password;
    }

    public string GetVersion()
    {
        //MyService is a simple static service provider
        return MyService.GetVersion(_url, _username, _password);
    }
}

public class Advanced : BaseClient
{
    private static AdvancedClient _instance;
    private static readonly object padlock = new object();

    public static AdvancedClient Instance
    {
        get
        {
            lock (padlock)
            {
                if (_instance == null)
                {
                    _instance = new AdvancedClient(true);
                }
                return _instance;
            }
        }
    }

    public void DoAdvancedMethod()
    {
        MyService.DoSomething(_url, _username, _password);
    }
}

したがって、BaseClient.Instance.SetInfo("http://myUrl", "myUser", "myPassword"); を使用すると、AdvancedClient.Instance.DoAdvancedMethod() の場合、AdvancedClient シングルトンは BaseClient シングルトンと同じ基本メンバー インスタンスを使用しますか?

4

4 に答える 4

3

ジェネリックを使用してこのタイプのソリューションを実装する方がはるかに簡単であることが常にわかっています。

public class Singleton<T> where T : class
{

    protected Singleton()
    {
    }

    public static T Instance
    {
        get { return SingletonFactory.instance; }
    }

    public void SetInfo(string url, string username, string password)
    {
        ...
    }

    public string GetVersion()
    {
        ...
    }

    class SingletonFactory
    {

        internal static readonly T instance;

        static SingletonFactory()
        {
            ConstructorInfo constructor = typeof(T).GetConstructor(
                       BindingFlags.Instance | BindingFlags.NonPublic,
                       null, new System.Type[0],
                       new ParameterModifier[0]);

            if (constructor == null)
                throw new Exception(
                    "Target type is missing private or protected no-args constructor: type=" + 
                    typeof(T).FullName);
            try
            {
                instance = constructor.Invoke(new object[0]) as T;
            }
            catch (Exception e)
            {
                throw new Exception(
                    "Failed to create target: type=" + typeof(T).FullName, e);
            }
        }

    }

}

public class Advanced : Singleton<Advanced>
{
    ...
}
于 2012-10-19T03:54:54.557 に答える
1

冗談です:)これが私の解決策です:

独立したクラスを使用して共有メンバーを格納し、AdvancedClient シングルトンの作成時に BaseClient シングルトンを取得します。

public class ClientInfo
{
    public string Url { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
}

public class BaseClient
{
    protected ClientInfo _info;

    private static BaseClient _instance;
    private static readonly object padlock = new object();

    public static BaseClient Instance
    {
        get
        {
            lock (padlock)
            {
                if (_instance == null)
                {
                    _instance = new BaseClient(true);
                }
                return _instance;
            }
        }
    }

    public ClientInfo Info
    {
        get
        {
            if(_info == null)
            {
                _info = new ClientInfo();
            }

            return _info;
        }
    }

    public void SetInfo(string url, string username, string password)
    {
        Info.Url = url;
        Info.Username = username;
        Info.Password = password;
    }

    public string GetVersion()
    {
        //MyService is a simple static service provider
        return MyService.GetVersion(Info.Url, Info.Username, Info.Password);
    }
}

public class Advanced : BaseClient
{
    private static AdvancedClient _instance;
    private static readonly object padlock = new object();

    public static AdvancedClient Instance
    {
        get
        {
            lock (padlock)
            {
                if (_instance == null)
                {
                    _instance = new AdvancedClient(true);
                    _instance._info = BaseClient.Instance.Info;
                }
                return _instance;
            }
        }
    }

    public void DoAdvancedMethod()
    {
        MyService.DoSomething(Info.Url, Info.Username, Info.Password);
    }
}
于 2012-10-22T13:45:44.847 に答える
0

は両方のクラスでプライベートであるため_instance、これらは2つの異なる変数です。_instance共有するには保護する必要があります。派生クラスは、基本クラスのプライベートメンバーにアクセスできません。

于 2012-10-18T20:06:59.857 に答える
0

基本クラスのシングルトンの意味を次のように変更できます。

public static BaseClient Instance
{
    get
    {
        lock (padlock)
        {
            if (_instance == null)
            {
                _instance = (BaseClient)(new AdvancedClient(true));
            }
            return _instance;
        }
    }
}
于 2012-10-18T19:56:24.733 に答える