c# – Ninject Memoize Singleton Scope中的实例
|
我正在使用Ninject来实例化一些带有构造函数arg的对象,例如:
class MyClass
{
public MyClass(string myArg)
{
this.myArg = myArg;
}
}
我需要这个类的实例数量直到运行时才知道,但我想要做的是确保myArg的每个变体产生一个不同的单例实例(因此要求两次相同的值会返回相同的实例,但是不同的args返回不同的实例). 有没有人知道一个好的,最好是内置的方式这样做? 我找到了一篇为Ninject How To Ensure One Instance per Variation of Activation Parameters的旧版本编写的文章,但希望有更新版本的更整洁的解决方案. 编辑 以下是我使用的内容,改编自Akim的答案如下: private readonly ConcurrentBag<string> scopeParameters = new ConcurrentBag<string>();
internal object ParameterScope(IContext context,string parameterName)
{
var param = context.Parameters.First(p => p.Name.Equals(parameterName));
var paramValue = param.GetValue(context,context.Request.Target) as string;
paramValue = string.Intern(paramValue);
if (paramValue != null && !scopeParameters.Contains(paramValue))
{
scopeParameters.Add(paramValue);
}
return paramValue;
}
public override void Load()
{
Bind<MyClass>()
.ToSelf()
.InScope(c => ParameterScope(c,"myArg"));
Bind<IMyClassFactory>()
.ToFactory();
}
解决方法
您可以通过使用IBindingNamedWithOrOnSyntax< T>提供自定义范围来实现需求行为.用于MyClass绑定的InScope(Func< IContext,object> scope)方法
因此,您需要从Func< IContext,object>返回第一个构造函数参数的值. scope并确保garbage-collector不会收集它. 这是一个片段: public class Module : NinjectModule
{
// stores string myArg to protect from CG
ConcurrentBag<string> ParamSet = new ConcurrentBag<string>();
public override void Load()
{
Bind<MyClass>()
.ToSelf()
// custom scope
.InScope((context) =>
{
// get first constructor argument
var param = context.Parameters.First().GetValue(context,context.Request.Target) as string;
// retrieves system reference to string
param = string.Intern(param);
// protect value from CG
if(param != null && ParamSet.Contains(param))
{
// protect from GC
ParamSet.Add(param);
}
// make Ninject to return same instance for this argument
return param;
});
}
}
ps:full sample code with unittests (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
