13

各派生クラスを強制的に Singleton にする抽象クラスを作成するにはどうすればよいですか? 私はC#を使用しています。

4

7 に答える 7

6

シングルトンには静的アクセスが必要であり、強制できないため、これは機能しません。

シングルトンの実装と例については、「 C#でのシングルトンパターンの実装」を参照してください。

于 2010-05-18T07:36:36.690 に答える
4

コンパイル時のチェックを有効にしたい場合、これは不可能です。実行時チェックを使用すると、これを行うことができます。きれいではありませんが、可能です。次に例を示します。

public abstract class Singleton
{
    private static readonly object locker = new object();
    private static HashSet<object> registeredTypes = new HashSet<object>();

    protected Singleton()
    {
        lock (locker)
        {
            if (registeredTypes.Contains(this.GetType()))
            {
                throw new InvalidOperationException(
                    "Only one instance can ever  be registered.");
            }
            registeredTypes.Add(this.GetType());
        }
    }
}

public class Repository : Singleton
{
    public static readonly Repository Instance = new Repository();

    private Repository()
    {
    }
}
于 2010-05-18T07:44:18.807 に答える
3

シングルトンとは、プライベート コンストラクターを持つことを意味します。しかし、プライベート メンバーは継承できないことがわかっています。C++ にはテンプレートがあったため、テンプレート クラスからシングルトンを作成できました。C# にはテンプレートがないため、必要なシングルトンごとに独自のプライベート コンストラクターを作成する必要があります。

于 2010-05-18T07:44:09.200 に答える
2

Java または C# のクラスは「ファーストクラス」ではありません。クラスの静的部分は、サブクラスによって継承またはオーバーライドできません。詳細については、この回答を参照してください。さらに、メタクラスの概念がありません。

Smalltalk や Ruby などの言語Singletonでは、メソッドを定義する新しいメタクラスを定義できますgetInstance。次に、メタクラスを定義ClassAClassBてインスタンスにすることができます。Singleton次に、両方のクラスが、インスタンスまたはgetInstanceの作成に使用できるメソッドを自動的に公開します。かっこよくない?実際には、メタクラスを頻繁に使用することはありません。シングルトンは、実際には意味があり、私が認識している唯一の使用法です。objectAobjectB

于 2010-05-18T07:52:52.423 に答える
0

ここで、Singleton 継承の実装を示します。

using System;
using System.Reflection;

namespace Mik.Singleton
{
    class Program
    {
        static void Main()
        {
            //You can not create an instance of class directly
            //Singleton1 singleton1 = new Singleton1();

            Singleton1 singleton1 = Singleton1.Instance;
            Singleton2 singleton2 = Singleton2.Instance;

            Console.WriteLine(singleton1.Singleton1Text);
            Console.WriteLine(singleton2.Singleton2Text);

            Console.ReadLine();
        }
    }

    public class SingletonBase<T> where T : class
    {
        #region Singleton implementation

        private static readonly object lockObj = new object();
        private static T _instance;

        protected SingletonBase() { }

        public static T Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (lockObj)
                    {
                        if (_instance == null)
                            _instance = CreateInstance();
                    }
                }
                return _instance;
            }
        }

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

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

                return instance;
            }
            catch (Exception e)
            {
                throw new Exception(
                    "Failed to create target: type=" + typeof(T).FullName, e);
            }
        }

        #endregion Singleton implementation
    }

    public class Singleton1 : SingletonBase<Singleton1>
    {
        private Singleton1() { }

        public string Singleton1Text { get; } = "Singleton1Text value";
    }

    public class Singleton2 : SingletonBase<Singleton2>
    {
        private Singleton2() { }

        public string Singleton2Text { get; } = "Singleton2Text value";
    }
}
于 2019-05-29T12:44:23.157 に答える