Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Singleton范围内的Ninject Memoize实例_C#_Dependency Injection_Inversion Of Control_Ninject_Garbage Collector - Fatal编程技术网

C# Singleton范围内的Ninject Memoize实例

C# Singleton范围内的Ninject Memoize实例,c#,dependency-injection,inversion-of-control,ninject,garbage-collector,C#,Dependency Injection,Inversion Of Control,Ninject,Garbage Collector,我使用Ninject实例化一些传递了构造函数arg的对象,例如: class MyClass { public MyClass(string myArg) { this.myArg = myArg; } } 我需要的这个类的实例数在运行时之前是未知的,但我要做的是确保myArg的每个变体都会产生不同的单例实例(因此两次请求相同的值会返回相同的实例,但不同的arg会返回不同的实例) 有人知道这样做的好方法吗,最好是内置的 我发现一篇文章是为旧版本的Ninj

我使用Ninject实例化一些传递了构造函数arg的对象,例如:

class MyClass
{
    public MyClass(string myArg)
    {
        this.myArg = myArg;
    }
}
我需要的这个类的实例数在运行时之前是未知的,但我要做的是确保
myArg
的每个变体都会产生不同的单例实例(因此两次请求相同的值会返回相同的实例,但不同的arg会返回不同的实例)

有人知道这样做的好方法吗,最好是内置的

我发现一篇文章是为旧版本的Ninject写的,但我希望新版本能有一个更整洁的解决方案

编辑

以下是我的答案,改编自阿基姆的回答:

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();
}
private readonly ConcurrentBag scopeParameters=new ConcurrentBag();
内部对象参数范围(IContext上下文,字符串参数名称)
{
var param=context.Parameters.First(p=>p.Name.Equals(parameterName));
var paramValue=param.GetValue(context,context.Request.Target)作为字符串;
paramValue=string.Intern(paramValue);
if(paramValue!=null&&!scopeParameters.Contains(paramValue))
{
scopeParameters.Add(paramValue);
}
返回参数值;
}
公共覆盖无效负载()
{
绑定()
.ToSelf()
.InScope(c=>参数范围(c,“myArg”);
绑定()
.ToFactory();
}

您可以通过使用
IBindingNamedWithOrOnSyntax InScope(Func scope)
方法为
MyClass
绑定提供自定义作用域来实现require行为

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

所以,您需要从
Func 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;
                });
    }
}
公共类模块:Ninject模块
{
//存储字符串myArg以防止CG攻击
ConcurrentBag ParamSet=新ConcurrentBag();
公共覆盖无效负载()
{
绑定()
.ToSelf()
//自定义范围
.InScope((上下文)=>
{
//获取第一个构造函数参数
var param=context.Parameters.First().GetValue(context,context.Request.Target)作为字符串;
//检索对字符串的系统引用
param=string.Intern(param);
//保护CG的价值
if(param!=null&&ParamSet.Contains(param))
{
//保护免受GC攻击
ParamSet.Add(param);
}
//使Ninject返回此参数的相同实例
返回参数;
});
}
}

ps:

我非常喜欢这个解决方案的简单性,我在维基上得到了一些额外的帮助。不过,这些实例需要来自工厂,您知道这是否与工厂扩展兼容吗?我想一定会的。它肯定能用!看,我在我的代码中整理了一下您的示例,以便告诉它使用哪个参数,而不是总是使用第一个参数,并且我编写了一些测试。非常好用,谢谢!!检查抽象工厂的自动实现