我正在使用 Ninject 来实例化一些传递了构造函数 arg 的对象,例如:
class MyClass
{
public MyClass(string myArg)
{
this.myArg = myArg;
}
}
我需要的此类实例的数量直到运行时才知道,但我想做的是确保 myArg
的每个变体都会产生不同的单例实例(因此要求相同的值两次返回相同的实例,但不同的参数返回不同的实例)。
有谁知道这样做的好方法,最好是内置的方法?
我找到一篇为旧版 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> InScope(Func<IContext, object> scope)
提供自定义范围来实现要求行为MyClass
的方法绑定(bind)
Indicates that instances activated via the binding should be re-used as long as the object returned by the provided callback remains alive (that is, has not been garbage collected).
因此,您需要从 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;
});
}
}
关于c# - 在单例范围内注入(inject) Memoize 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14502396/