5

我正在使用 Ninject 实例化一些带有构造函数参数的对象,例如:

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

1 回答 1

3

您可以通过使用绑定IBindingNamedWithOrOnSyntax<T> InScope(Func<IContext, object> scope)方法提供自定义范围来实现需求行为MyClass

表示只要提供的回调返回的对象保持活动状态 (即尚未被垃圾回收),就应该重新使用通过绑定激活的实例。

因此,您需要返回第一个构造函数参数的值,Func<IContext, object> scope并确保不会收集它。

这是一个片段:

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:带有单元测试的完整示例代码

于 2013-01-24T14:54:43.547 回答