gpt4 book ai didi

c# - 如何为泛型创建一个完全懒惰的单例

转载 作者:太空宇宙 更新时间:2023-11-03 22:01:25 25 4
gpt4 key购买 nike

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

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.htmlhttp://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
{
}

错误 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>'

错误 2 处的错误是:

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

如何解决这个问题,使其与上面提到的 2 篇文章一致?任何其他想法或建议表示赞赏。

我的实现是否打破了单例模式?

最佳答案

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

写作时

Singleton<IMyInterface>

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

对于错误2,

Singleton<IMyInterface>.Instance = CreateEngineInstance();

您正在尝试为只读属性赋值。因此,您需要在 Instance 属性上定义一个 setter 才能使该行生效。

更新

按照这些思路应该可以为您完成:

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>();

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

您还应该查看依赖注入(inject)模式,它似乎接近您想要实现的目标,还应该查看已经执行此操作的现有 DI 框架(NInject、Nhibernate)。

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

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com