单例工厂(基类)没有'实例
本文关键字:实例 没有 工厂 基类 单例 | 更新日期: 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
}