加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – Ninject Memoize Singleton Scope中的实例

发布时间:2020-12-15 05:37:41 所属栏目:百科 来源:网络整理
导读:我正在使用Ninject来实例化一些带有构造函数arg的对象,例如: class MyClass{ public MyClass(string myArg) { this.myArg = myArg; }} 我需要这个类的实例数量直到运行时才知道,但我想要做的是确保myArg的每个变体产生一个不同的单例实例(因此要求两次相同
我正在使用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)方法

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

ps:full sample code with unittests

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读