Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.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# 配置Unity以解析接受修饰依赖项的类型,该依赖项具有随注入类型而变化的参数_C#_Dependency Injection_Inversion Of Control_Unity Container_Ioc Container - Fatal编程技术网

C# 配置Unity以解析接受修饰依赖项的类型,该依赖项具有随注入类型而变化的参数

C# 配置Unity以解析接受修饰依赖项的类型,该依赖项具有随注入类型而变化的参数,c#,dependency-injection,inversion-of-control,unity-container,ioc-container,C#,Dependency Injection,Inversion Of Control,Unity Container,Ioc Container,这是一个相当直截了当的装饰器模式场景,复杂的是装饰类型有一个构造函数参数,该参数依赖于它被注入的类型 我有这样一个界面: interface IThing { void Do(); } class RealThing : IThing { public RealThing(string configuration) { ... implementation ... } public void Do() { ...

这是一个相当直截了当的装饰器模式场景,复杂的是装饰类型有一个构造函数参数,该参数依赖于它被注入的类型

我有这样一个界面:

interface IThing
{
    void Do();
}
class RealThing : IThing
{
    public RealThing(string configuration)
    {
        ... implementation ...
    }

    public void Do()
    {
        ... implementation ...
    }
}
class DecoratingThing : IThing
{
    IThing _innerThing;

    public DecoratingThing(IThing thing)
    {
        _innerThing = thing;    
    }

    public void Do()
    {
        _innerThing.Do();
    }
}
以及这样的实现:

interface IThing
{
    void Do();
}
class RealThing : IThing
{
    public RealThing(string configuration)
    {
        ... implementation ...
    }

    public void Do()
    {
        ... implementation ...
    }
}
class DecoratingThing : IThing
{
    IThing _innerThing;

    public DecoratingThing(IThing thing)
    {
        _innerThing = thing;    
    }

    public void Do()
    {
        _innerThing.Do();
    }
}
还有像这样的装饰师:

interface IThing
{
    void Do();
}
class RealThing : IThing
{
    public RealThing(string configuration)
    {
        ... implementation ...
    }

    public void Do()
    {
        ... implementation ...
    }
}
class DecoratingThing : IThing
{
    IThing _innerThing;

    public DecoratingThing(IThing thing)
    {
        _innerThing = thing;    
    }

    public void Do()
    {
        _innerThing.Do();
    }
}
最后,我有一些类型需要一个
IThing
,称为
Depender1
Depender2
等等

class DependerX()
{
    public DependerX(IThing thing)
    {
        ... implementation ...
    }
}
我想配置一个IOC容器来解析
DependerX
的实例,以便它们被注入
RealThing
,并用
decormingthing
装饰重要提示:每个
DependerX
类型都要求将不同的
配置值
传递给其
实体的构造函数
,在每种情况下都说“ConfigX”。e、 g.IoC容器完成的工作可能是:

new Depender1(new DecoratingThing(new RealThing("Config1")));
new Depender2(new DecoratingThing(new RealThing("Config2")));
。。。等等

在Unity中,这似乎很难配置,因为我必须在装饰器中混合装饰:

container.RegisterType<IThing, DecoratingThing>("ConfigX",
    new InjectionFactory(container => new DecoratingThing(new RealThing("ConfigX"));

container.RegisterType<DependerX>(
    new InjectionConstructor(new ResolvedParameter<IThing>("ConfigX");
这至少消除了重复,但我仍然必须将
RealThing
的构造嵌入
DecoratingThing
——这意味着我不能独立地改变它们的生命周期。我无法再次注册
以执行此操作,因为我已用光了该接口的名称注册。如果我想这样做,我必须引入另一组命名实例,如下所示:

void RegisterDepender<TDepender>(IUnityContainer container, string config)
{
    string realConfig = "Real" + config;

    container.RegisterType<TDepender>(new InjectionConstructor(
        new ResolvedParameter<IThing>(config)));
    container.RegisterType<IThing, DecoratingThing>(config,
        new InjectionFactory(c => new DecoratingThing(
            container.Resolve<IThing>(realConfig))));
    container.RegisterType<IThing, RealThing>(realConfig,
        new ContainerControlledLifetimeManager(),
        new InjectionConstructor(config));
}
void RegisterDepender(IUnityContainer容器,字符串配置)
{
字符串realConfig=“Real”+config;
container.RegisterType(新注入构造函数)(
新的解析参数(配置));
container.RegisterType(配置,
新注入工厂(c=>新装饰(
container.Resolve(realConfig));
container.RegisterType(realConfig,
新建ContainerControlled LifetimeManager(),
新的InjectionConstructor(config));
}
这真的是最好的选择吗?这让人觉得很复杂,而且对于那些后来的人来说,可能很难去摸索。其他IoC容器是否有一种引人注目的方式来涵盖这种情况?由于注入如何工作的模式对每个DependerX都是重复的,因此有没有办法只在顶部(
DependerX
)级别使用命名实例


还有其他意见吗?

你有没有想过让你的装饰程序基于Unity拦截功能?然后,只需使用这个拦截器一次,就可以很容易地说“截获对
的调用”

container.AddNewExtension<Interception>();
container.RegisterType<IThing>(new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<DecoratingThingBehavior>());

班级设计本身似乎是合理的。下面是一个基于约定的容器配置,基本上可以做到这一点:

public class MyConventions : UnityContainerExtension
{
    protected override void Initialize()
    {
        var dependers = from t in typeof(IThing).Assembly.GetExportedTypes()
                        where t.Name.StartsWith("Depender")
                        select t;

        foreach (var t in dependers)
        {
            var number = t.Name.TrimStart("Depender".ToArray());
            var realName = "Real" + number;
            var decoName = "Deco" + number;
            var config = "Config" + number;
            this.Container.RegisterType<IThing, RealThing>(realName, 
                new InjectionConstructor(config));
            this.Container.RegisterType<IThing, DecoratingThing>(decoName,
                new InjectionConstructor(
                    new ResolvedParameter<IThing>(realName)));
            this.Container.RegisterType(t,
                new InjectionConstructor(
                    new ResolvedParameter<IThing>(decoName)));
        }
    }
}

我认为这是一种不同的装饰方法,而不是它的实现。我已经考虑过了,我认为在这个特殊的案例中,我并没有真正处理一个合适的交叉关注点。它的范围非常具体,并且装饰器的行为取决于所调用的方法。我认为在这种情况下,我可能会将复杂性转换为拦截的逻辑。我拥有的装饰器是预先存在的,非常复杂,并且在其他地方使用,所以重构是非常重要的。考虑到问题中的信息,这是一个很好的建议,所以我给它加1分。谢谢。我认为在我的特定场景中,基于约定的方法是可行的。这并不是说其他方法(如上面的拦截思想)并不同样有效。很高兴听到我在这里还没有偏离常规!