Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.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 Decorator扩展因多个实现而失败_C#_.net 4.0_Dependency Injection_Unity Container_Decorator - Fatal编程技术网

C# Unity Decorator扩展因多个实现而失败

C# Unity Decorator扩展因多个实现而失败,c#,.net-4.0,dependency-injection,unity-container,decorator,C#,.net 4.0,Dependency Injection,Unity Container,Decorator,我已经为这个问题挣扎了几天,但我仍然不知道如何解决它 我已经为Unity容器创建了一个容器扩展,使我能够轻松地在容器中注册decorator类。这是我目前拥有的实现,与本文中的实现几乎相同: 这在很大程度上创造了奇迹。当我有一个类实现了两个接口时,问题就开始了,一个是修饰的,另一个不是 这是我正在努力实现的当前测试用例: private interface IAny<T> {} private interface IAnotherInterface {} private class

我已经为这个问题挣扎了几天,但我仍然不知道如何解决它

我已经为Unity容器创建了一个容器扩展,使我能够轻松地在容器中注册decorator类。这是我目前拥有的实现,与本文中的实现几乎相同:

这在很大程度上创造了奇迹。当我有一个类实现了两个接口时,问题就开始了,一个是修饰的,另一个不是

这是我正在努力实现的当前测试用例:

private interface IAny<T> {}
private interface IAnotherInterface {}
private class Base<T> : IAnotherInterface, IAny<T> {}   
private class Decorator1<T> : IAny<T>
{
    internal readonly IAny<T> Decorated;

    public Decorator1(IAny<T> _decorated)
    {
        Decorated = _decorated;
    }
}

[TestMethod]
public void DecoratorExtensionDoesNotInterfereWithNormalRegistrations()
{
    // Arrange
    var container = new UnityContainer()
        .AddNewExtension<DecoratorExtension>()
        .RegisterType<Base<string>>(new ContainerControlledLifetimeManager())
        .RegisterType<IAny<string>, Decorator1<string>>()
        .RegisterType<IAny<string>, Base<string>>()
        .RegisterType<IAnotherInterface, Base<string>>();

    // Act
    var decorated = container.Resolve<IAny<string>>();
    var normal = container.Resolve<IAnotherInterface>();
    var anotherDecorated = container.Resolve<IAny<string>>();
    var anotherNormal = container.Resolve<IAnotherInterface>();

    // Assert
    Assert.IsInstanceOfType(normal, typeof (IAnotherInterface));
    Assert.IsInstanceOfType(decorated, typeof (Decorator1<string>));
    Assert.AreSame(normal, anotherNormal);
    Assert.AreSame(decorated, anotherDecorated);
}
在这一行:

    var normal = container.Resolve<IAnotherInterface>();
var normal=container.Resolve();
我不知道该怎么办。我必须在我们的项目中暂时禁用单例,这样才能按预期工作。我想要的是
Base
实例是一个sintleton,但当我请求
IAny
时,它将创建一个新实例,并装饰相同的Base


这仍然在使用.Net 4.0,因此我在这里坚持使用Unity 2.1(虽然在本例中并不重要)。

我不确定这是否是您想要的,但我认为这在您测试的特定情况下起到了作用:

container.RegisterType(
新的ContainerControlled LifetimeManager(),“内部”);
container.RegisterType(
新注入构造函数(
新的解析参数(类型(IAny),“内部”);
容器注册(新注射工厂)(
c=>c.Resolve(“内部”);

你不需要这个扩展。

我解决这个问题已经有一段时间了,所以我想复制我从EntLib团队得到的答案会很好

它基本上可以归结为我用来注册decorator实例的构建键。在我的代码中,实例实际上是用基类类型注册的,而我需要用实际的decorator类型注册它


该问题的建议解决方案对我们非常有效。

您是否考虑过切换到另一个框架?@Steven嘿,Steven,我真的期待您的评论,您没有让xD失望。是的,我知道有些容器支持这种开箱即用的功能,比如Windsor或你的Simple Injector,但我们这里有一个非常大的项目,有些东西在某些地方与容器绑定(在某些地方,像webforms和其他东西一样,injection不受本机支持),因此,只有在完全不可能做到这一点的情况下,我才会走这条路。例如,我可以将实现拆分为多个类,但这是最后的解决方案,因为它会显著影响代码库。@另一个原因是我们还有一个自定义设计的企业库应用程序块。它实际上是在我们开始使用IoC之前创建的,将它与unity集成非常容易(有一个已经实现的扩展,可以在容器中自动加载应用程序块)。我必须实现适配器逻辑以将其与其他容器集成。其实这并不难,只是另一个让事情变得复杂的方面。我很高兴我没有达到你的期望:-)我不认为温莎对装饰师的支持比Unity的好。Autofac有更好的支持,但当涉及到应用通用装饰器时,Simple Injector是这里的王者。它本机理解泛型类型约束,并允许您根据静态类型信息有条件地应用修饰符。是的,这是一种在Unity上进行开箱即用修饰符的好方法,但显然这是一个麻烦。我目前在一个类中有5个链式装饰器。注册的代码将是荒谬的不可读的,并且很难维护。另一个问题是必须了解每个构造函数,这同样存在维护问题。我想在这里我会认为这是这个问题的最后一个解决办法:(考虑到我在这个问题中提出的问题,这是一个完全有效的答案。
internal struct DecoratorRegistration
{
    public int Order { get; set; }
    public Type Type { get; set; }
}
private interface IAny<T> {}
private interface IAnotherInterface {}
private class Base<T> : IAnotherInterface, IAny<T> {}   
private class Decorator1<T> : IAny<T>
{
    internal readonly IAny<T> Decorated;

    public Decorator1(IAny<T> _decorated)
    {
        Decorated = _decorated;
    }
}

[TestMethod]
public void DecoratorExtensionDoesNotInterfereWithNormalRegistrations()
{
    // Arrange
    var container = new UnityContainer()
        .AddNewExtension<DecoratorExtension>()
        .RegisterType<Base<string>>(new ContainerControlledLifetimeManager())
        .RegisterType<IAny<string>, Decorator1<string>>()
        .RegisterType<IAny<string>, Base<string>>()
        .RegisterType<IAnotherInterface, Base<string>>();

    // Act
    var decorated = container.Resolve<IAny<string>>();
    var normal = container.Resolve<IAnotherInterface>();
    var anotherDecorated = container.Resolve<IAny<string>>();
    var anotherNormal = container.Resolve<IAnotherInterface>();

    // Assert
    Assert.IsInstanceOfType(normal, typeof (IAnotherInterface));
    Assert.IsInstanceOfType(decorated, typeof (Decorator1<string>));
    Assert.AreSame(normal, anotherNormal);
    Assert.AreSame(decorated, anotherDecorated);
}
System.InvalidCastException: Unable to cast object of type 'Decorator1`1[System.String]' to type 'IAnotherInterface'.
    var normal = container.Resolve<IAnotherInterface>();