单例工厂(基类)没有'实例

本文关键字:实例 没有 工厂 基类 单例 | 更新日期: 2023-09-27 18:03:02

我有下面的类来创建一个Singelton:

public class Singleton<T> where T : class
{
    #region Constructors
    protected Singleton()
    { }
    #endregion Constructors
    #region Properties
    private static T instance;
    public static T GetInstance()
    {
        if (instance == null)
        { instance = SingletonCreator.Singleton; }
        return instance;
    }
    public static void ClearInstance()
    { instance = null; }
    #endregion Properties
    #region Inner classes
    private class SingletonCreator
    {
        #region Properties
        private static readonly T instance = typeof(T).InvokeMember(typeof(T).Name,
            BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic, null, null, null, CultureInfo.CurrentCulture) as T;
        internal static T Singleton
        { get { return instance; } }
        #endregion Properties
    }
    #endregion Inner classes
}

然后我创建了一个从这个类继承的类'Person',从而使它成为一个单例。

public class Person : Singleton<Person>
{
    #region Constructors
    protected Person() { }
    #endregion
    #region Properties
    public string Firstname { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    #endregion
}

最后,我有单元测试:

    [TestMethod]
    public void then_the_new_instance_should_have_default_values_for_the_properties()
    {
        Person.GetInstance().Age = 1;
        Person.GetInstance().Name = "Unit";
        Person.GetInstance().Firstname = "Test";
        Person.ClearInstance();
        Assert.AreEqual(Person.GetInstance().Age, 0, "The age property of the requested instance is incorrect.");
        Assert.AreEqual(Person.GetInstance().Name, "", "The name property of the requested instance is incorrect.");
        Assert.AreEqual(Person.GetInstance().Firstname, "", "The firstname property of the requested instance is incorrect.");
    }

我的猜测是单元测试应该通过,因为当前一个实例被清除时,我询问了一个实例。

但是person对象具有与ClearInstance()方法之前的对象相同的值。

我认为这是一个安全的实现,但似乎我在这里错过了一些东西。

有人知道吗?

单例工厂(基类)没有'实例

原因是在创建单例时看起来有两个层次。你真正的单例实际上是SingletonCreator.instance,并且那个永远不会被清除。

Singleton<T>创建实例时,它调用SingletonCreator.instance来获得实际的实例。当您清除时,您从Singleton<T>.instance中清除一个,但是下次创建时,它从已经有实例返回给您的SingletonCreator.instance中提取现有的一个。

我不认为你需要额外的SingletonCreator层。只需将该代码移动到Singleton<T>,就可以了。

public class Singleton<T> where T : class
{
    #region Constructors
    protected Singleton()
    { }
    #endregion Constructors
    #region Properties
    private static readonly object instanceLock = new object();
    private static T instance;
    public static T GetInstance()
    {
        if (instance == null)
        {
            lock(instanceLock)
            {
                if (instance == null)
                {
                    instance = typeof(T).InvokeMember(typeof(T).Name,
            BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic, null, null, null, CultureInfo.CurrentCulture) as T; 
                }
            }
        }
        return instance;
    }
    public static void ClearInstance()
    { instance = null; }
    #endregion Properties
}