我有以下两个班级:
Singleton - >用于定义Singleton
/// <summary>
/// By inheriting from this member you indicate that the implementing class should be implemented as a Singleton.
/// A singleton does mean that only one instance of the Singleton can exists at a time, even when multiple threads
/// are requesting an instance.
/// </summary>
/// <typeparam name="T">The type for which to create a singleton.</typeparam>
public class Singleton<T> where T : class
{
#region Constructors
/// <summary>
/// A protected constructor to make sure that the compiler doesn't add a default public one.
/// A public one would mean that you can create an instance of this class directly which is a violation of the
/// Singleton pattern.
/// </summary>
protected Singleton()
{
}
#endregion Constructors
#region Properties
/// <summary>
/// An instance of the <see typeparam="T" />.
/// </summary>
private static T instance;
private static readonly object instanceLock = new object();
/// <summary>
/// Gets an instance of <see typeparam="T" />. When no instance is existing, a new one is created, otherwise the
/// already existing
/// is returned.
/// </summary>
/// <param name="constructionParameters">The parameters that are needed for the construction of this object.</param>
/// <returns>An instance of <see typeparam="T" />.</returns>
public static T GetInstance(params object[] constructionParameters)
{
if (!typeof(T).IsDefined(typeof(SingletonAttribute), false))
{ throw new InvalidOperationException("Still rework this."); }
if (instance == null)
{
lock (instanceLock)
{
if (instance == null)
{
instance = typeof(T).InvokeMember(typeof(T).Name,
BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic, null, null,
constructionParameters, CultureInfo.CurrentCulture) as T;
}
}
}
return instance;
}
/// <summary>
/// Clears the current instance.
/// </summary>
public static void ClearInstance()
{
instance = null;
}
#endregion Properties
}
另一个类是一个初始化程序,它允许我将任何对象构造为Singleton。
/// <summary>
/// Provides an easy way to initialize a class as a Singleton.
/// </summary>
/// <typeparam name="T">The type of the class that should be instantiated as a Singleton.</typeparam>
public class SingletonInitializer<T> : Singleton<T> where T : class
{
#region Constructors
/// <summary>
/// A private constructor that prevents the compiler from adding a default public one.
/// </summary>
[ExcludeFromCodeCoverage]
private SingletonInitializer()
{
}
#endregion Constructors
#region Methods
/// <summary>
/// Gets an instance of <see typeparam="T" />. When no instance is existing, a new one is created, otherwise the
/// already existing
/// is returned.
/// </summary>
/// <param name="constructionParameters">The parameters that are needed for the construction of this object.</param>
/// <returns>An instance of <see typeparam="T" />.</returns>
public static new T GetInstance(params object[] constructionParameters)
{
if (!typeof(T).IsDefined(typeof(SingletonAttribute), false))
{ throw new InvalidOperationException("Still rework this."); }
Singleton<T>.GetInstance(constructionParameters);
return default(T);
}
#endregion
}
到目前为止,这不是问题。我会给你一个小例子:
我将把我作为单身人士加载的课程:
public class Car
{
#region Constructors
/// <summary>
/// Creates a new instance of a <see cref="Person" />.
/// </summary>
protected Car()
{
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the name of the <see cref="Person" />.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the age of the <see cref="Person" />.
/// </summary>
public int Age { get; set; }
#endregion
}
允许通过Singleton范围更改此类属性的代码。
SingletonInitializer<Car>.GetInstance().Name = "Ford";
SingletonInitializer<Car>.GetInstance().Age = 1;
到目前为止,一切正常,但在上面的场景中,用户可以自己创建一个类,让它继承自Singleton,如下所示:
public class Person : Singleton<Person>
{
#region Constructors
/// <summary>
/// Creates a new instance of a <see cref="Person" />.
/// </summary>
protected Person()
{
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the firstname of the <see cref="Person" />.
/// </summary>
public string Firstname { get; set; }
/// <summary>
/// Gets or sets the name of the <see cref="Person" />.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the age of the <see cref="Person" />.
/// </summary>
public int Age { get; set; }
#endregion
}
然后,用户可以调用以下代码,通过Singleton范围更改此类的属性:
Person.GetInstance();
我想避免任何人都可以在一个对象上调用GetInstance(),换句话说,除了SingletonInitializer之外,不应该在任何对象上使用GetInstance。如果可能,我想在编译时检测到这一点,并让Visual Studio在遇到这种行为时生成错误。
所以,这是一个非常大的问题,但我想让范围非常明确。 希望有人能让我走上正轨。
答案 0 :(得分:1)
您可以将课程密封http://msdn.microsoft.com/en-us/library/88c54tsw.aspx或将方法设为内部http://msdn.microsoft.com/en-us/library/7c5ka91b.aspx。密封的方法更安全。
编辑:这是一个实现,它将保证每个类型的应用程序范围一个实例:
public class SingletonIntializer<T>
{
public T GetInstance(params object[] @params)
{
if (!SingletonContainer.ContainsType(typeof(T)))
{
SingletonContainer.CreateInstance(typeof(T), @params);
}
return (T)SingletonContainer.GetInstance(typeof(T));
}
}
internal static class SingletonContainer
{
private static Dictionary<Type, object> internalContainer = new Dictionary<Type, object>();
public static bool ContainsType(Type type)
{
return internalContainer.ContainsKey(type);
}
public static bool CreateInstance(Type type, object[] @params)
{
if (ContainsType(type))
{
return false;
}
internalContainer[type] = Activator.CreateInstance(type, @params);
return true;
}
public static object GetInstance(Type type)
{
if (!ContainsType(type))
{
return null;
}
return internalContainer[type];
}
}