我有以下课程来创建一个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
}
然后我创建了一个班级&#39; Person&#39;它继承自这个类,从而使它成为一个单身人士。
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()方法之前的对象具有相同的值。
我认为这是一个安全的实现,但似乎我在这里遗漏了一些东西。
有人有线索吗?
答案 0 :(得分:3)
原因是你在创建单身时看起来有两个层次。你的真正的单身实际上是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
}