我的通用单例提供程序具有以下代码实现:

public sealed class Singleton<T> where T : class, new()
{
     Singleton()
     {
     }

     public static T Instance
     {
          get { return SingletonCreator.instance; }
     }

     class SingletonCreator
     {
          static SingletonCreator()
          {
          }

          internal static readonly T instance = new T();
     }
}


该示例来自2篇文章,我合并了代码以获取所需的信息:

http://www.yoda.arachsys.com/csharp/singleton.html
http://www.codeproject.com/Articles/11111/Generic-Singleton-Provider

这就是我尝试使用上面的代码的方式:

public class MyClass
{
     public static IMyInterface Initialize()
     {
          if (Singleton<IMyInterface>.Instance == null  // Error 1
          {
               Singleton<IMyInterface>.Instance = CreateEngineInstance();  // Error 2
               Singleton<IMyInterface>.Instance.Initialize();
          }

          return Singleton<IMyInterface>.Instance;
     }
}


和界面:

public interface IMyInterface
{
}


Error 1处的错误是:

'MyProject.IMyInterace' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'MyProject.Singleton<T>'


Error 2处的错误是:

Property or indexer 'MyProject.Singleton<MyProject.IMyInterface>.Instance' cannot be assigned to -- it is read only


如何解决此问题,使其与上述2篇文章一致?任何其他想法或建议,表示赞赏。

我的实现会破坏Singleton模式吗?

最佳答案

基本上,您已经为单例类提供了类约束,以及new()约束。

写作时

Singleton<IMyInterface>


您使用的接口类型为T,这违反了您定义的类型约束。

对于错误2,

Singleton<IMyInterface>.Instance = CreateEngineInstance();


您正在尝试将值分配给只读属性。因此,您需要在Instance属性上定义一个设置器,该行才能工作。

更新资料

这些方针应该为您做:

public sealed class Singleton
{
     private static Hashtable bindings = new Hashtable();
     private static Hashtable instances = new Hashtable();

     private static void checkType(Type requested, Type bound)
     {
        if (requested.IsValueType)
            throw new Exception("Cannot bind a value type to a reference type");

        // also check type inheritance and other things...
     }

     private static void checkBinding(Type requested)
     {
        if (!(bindings.ContainsKey(requested)))
            throw new Exception(String.Format("Type {0} was not bound !", requested.FullName));
     }

     public static void Bind<T, U>() where U : class, new()
     {
        checkType(typeof(T), typeof(U));
        bindings[typeof(T)] = typeof(U);
     }

     public static T GetInstance<T>()
     {
        Type requested = typeof(T);
        Type bound = (Type) bindings[requested];

        checkBinding(requested);

        if (!instances.ContainsKey(requested)) {
            // We know that type "bound" was set with a new() class constraint
            instances[requested] = (T) Activator.CreateInstance(bound);
        }

        return (T) instances[requested];
     }
}


然后,您可以写:

 Singleton.Bind<IMyInterface, MyClass>();
 IMyInterface instance = Singleton.GetInstance<IMyInterface>();


如果要更进一步,还可以指定此提供程序创建的对象的生命周期,以便可以使用单例,或者让提供程序为每个调用返回一个新对象,依此类推。

您还应该看看依赖注入模式,它看起来很接近您要实现的目标,还应该看看已经做到这一点的现有DI框架(NInject,Nhibernate)。

关于c# - 如何为泛型创建完全懒惰的单例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9955435/

10-10 21:42