Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.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# 温莎城堡充满争议的生活方式_C#_.net_Dependency Injection_Instance_Castle Windsor - Fatal编程技术网

C# 温莎城堡充满争议的生活方式

C# 温莎城堡充满争议的生活方式,c#,.net,dependency-injection,instance,castle-windsor,C#,.net,Dependency Injection,Instance,Castle Windsor,我让我的IoC容器管理我的对象图的生命周期,并且似乎重用了一种特定的生活方式,这在目前是不可用的 例子 我需要通过将解析时间参数传入工厂来构造对象上下文,例如,当我传入字符串Dorothy时,我希望返回一个将使用字符串Dorothy实例化的个人的单例,如果它在容器中还不存在,或者是现有的Dorothy实例。将字符串参数Jane传递到我的工厂时也是如此-请返回Person Jane的singleton。可能还有Sally、Bob和其他许多人,这些完整的输入集只在运行时才被分解 手动执行 下面是另一

我让我的IoC容器管理我的对象图的生命周期,并且似乎重用了一种特定的生活方式,这在目前是不可用的

例子 我需要通过将解析时间参数传入工厂来构造对象上下文,例如,当我传入字符串Dorothy时,我希望返回一个将使用字符串Dorothy实例化的个人的单例,如果它在容器中还不存在,或者是现有的Dorothy实例。将字符串参数Jane传递到我的工厂时也是如此-请返回Person Jane的singleton。可能还有Sally、Bob和其他许多人,这些完整的输入集只在运行时才被分解

手动执行 下面是另一个示例,在我的自定义类中使用字典实现:

private readonly static IDictionary<string,IRecruiter> Recruiters
                        = new Dictionary<string, IRecruiter>();

private IRecruiter GetRecruiter(string recruiterId)
    {
    IRecruiter recruiter;
    if (!Recruiters.TryGetValue(recruiterId, out recruiter))
                    {
                    recruiter = this.donorFactory.CreateRecruiter(recruiterId);
                    Recruiters.Add(recruiterId,recruiter);
                    }
    return recruiter;
    }
private只读静态IDictionary招聘人员
=新字典();
私人IRecruiter GetRecruiter(字符串recruiterId)
{
IRecruiter招聘人员;
if(!Recruiters.TryGetValue(recruiterId,out recruiter))
{
recruiter=this.donorFactory.CreateRecruiter(recruiterId);
招聘人员。添加(招聘人员ID,招聘人员);
}
返回招聘人员;
}
donorFactory CreateRecruiter方法的作用如下:

return this.Create<IRecruiter>(new Arguments { { typeof(string), recruiterId }});
返回this.Create(新参数{{typeof(string),recruiterId});
和减少样板 我发现我经常使用这个模式,所以想知道是否有可能使用现有的温莎城堡生活方式来实现,或者是否有案例将此模式添加到温莎城堡本身

  • 在这种情况下,将组件注册为.Named不起作用,因为传入参数集在设计时是未知的
  • 如果使用GetHashCode或类似的东西作为字典的键,则该模式可以有一个通用实现,可以处理任何类型的参数(不仅仅是字符串)甚至参数集

我可以通过创建自定义作用域访问器找到一种方法:

public class ArgScopeAccessor : IScopeAccessor
{
    static readonly ConcurrentDictionary<string, ILifetimeScope> collection = new ConcurrentDictionary<string, ILifetimeScope>();

    public void Dispose()
    {
        foreach (var scope in collection)
            scope.Value.Dispose();
        collection.Clear();
    }

    public ILifetimeScope GetScope(CreationContext context)
    {
        string name = (string)context.AdditionalArguments["name"];
        return collection.GetOrAdd(name, n => new DefaultLifetimeScope());
    }
}
假设你的
IRecruiter
招聘人员是这样的:

public interface IRecruiter
{
    string Name { get; }
}

public class Recruiter : IRecruiter
{
    public Recruiter(string name)
    {
        Name = name;
    }

    public string Name { get; private set; }
}
container.AddFacility<TypedFactoryFacility>();

container.Register(Component.For<IRecruiterFactory>()
                            .AsFactory());
container.Register(Component.For<IRecruiter>()
                            .ImplementedBy<Recruiter>()
                            .LifestyleScoped<ArgScopeAccessor>());
然后,您可以设置容器以可重用的方式使用此作用域,如下所示:

public interface IRecruiter
{
    string Name { get; }
}

public class Recruiter : IRecruiter
{
    public Recruiter(string name)
    {
        Name = name;
    }

    public string Name { get; private set; }
}
container.AddFacility<TypedFactoryFacility>();

container.Register(Component.For<IRecruiterFactory>()
                            .AsFactory());
container.Register(Component.For<IRecruiter>()
                            .ImplementedBy<Recruiter>()
                            .LifestyleScoped<ArgScopeAccessor>());
container.AddFacility();
container.Register(Component.For())
.AsFactory());
container.Register(Component.For())
.由()实施
.lifestylescope());
现在,按姓名解析招聘人员将解析同一个实例:

IRecruiterFactory recruiterFactory = container.Resolve<IRecruiterFactory>();
IRecruiter jane1 = recruiterFactory.Create("Jane");
IRecruiter susan = recruiterFactory.Create("Susan");
IRecruiter jane2 = recruiterFactory.Create("Jane");

Console.WriteLine("Jane 1: " + jane1.GetHashCode());
Console.WriteLine("Jane 2: " + jane2.GetHashCode());
Console.WriteLine("Susan:  " + susan.GetHashCode());
IRecruiterFactory recruiterFactory=container.Resolve();
IRecruiter jane1=recruiterFactory.Create(“Jane”);
IRecruiter susan=recruiterFactory.Create(“susan”);
IRecruiter jane2=recruiterFactory.Create(“Jane”);
WriteLine(“jane1:+jane1.GetHashCode());
WriteLine(“jane2:+jane2.GetHashCode());
Console.WriteLine(“Susan:+Susan.GetHashCode());
显示:

Jane 1: 60467532 Jane 2: 60467532 Susan: 63249743 简1:60467532 简2:60467532 苏珊:63249743
显然,您可以创建一个不同的作用域访问器来处理您想要区分类型的任何其他方式,例如哈希代码或参数组合。但是,我没有看到在
ArgScopeAccessor
中更改
name
常量的方法,因为在配置容器上的作用域访问器时,无法传递构造函数参数。但是,这可以通过只指定常量的基类型和派生类型来解决。

使用文字名称字符串[“name”]在生产环境中不起作用(由于混淆),因此将尝试为该行想出一个替代方法,否则很好!