Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.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# 具有LifetimeManager奇怪行为的Unity RegisterType_C#_Inversion Of Control_Unity Container - Fatal编程技术网

C# 具有LifetimeManager奇怪行为的Unity RegisterType

C# 具有LifetimeManager奇怪行为的Unity RegisterType,c#,inversion-of-control,unity-container,C#,Inversion Of Control,Unity Container,我一直在玩Unity容器,并注意到一个奇怪的行为。我有一个类,它实现了多个接口。我希望这个类在应用程序的不同位置使用,并具有不同的生命周期。所以我将IFooDerived1映射到Foo作为单态,而IFooDerived2映射到Foo作为瞬态。但任何Foo的注册都会破坏Foo之前的注册 样本: interface IFoo { } interface IFooDerived1 { } interface IFooDerived2 { } class Foo : IF

我一直在玩Unity容器,并注意到一个奇怪的行为。我有一个类,它实现了多个接口。我希望这个类在应用程序的不同位置使用,并具有不同的生命周期。所以我将IFooDerived1映射到Foo作为单态,而IFooDerived2映射到Foo作为瞬态。但任何Foo的注册都会破坏Foo之前的注册

样本:

    interface IFoo { }
    interface IFooDerived1 { }
    interface IFooDerived2 { }
    class Foo : IFoo, IFooDerived1, IFooDerived2 { }

    static void Main(string[] args)
    {
        var container = new UnityContainer();

        container.RegisterType(typeof(IFoo), typeof(Foo), new ExternallyControlledLifetimeManager());
        container.RegisterType(typeof(IFooDerived1), typeof(Foo), new ContainerControlledLifetimeManager());
        container.RegisterType(typeof(IFooDerived2), typeof(Foo), new TransientLifetimeManager());

        foreach(var r in container.Registrations)
        {
            Console.WriteLine("{0} -> {1} : {2}", r.RegisteredType.Name, r.MappedToType.Name, r.LifetimeManagerType.Name);
        }
    }
输出:

    IFoo -> Foo : TransientLifetimeManager
    IFooDerived1 -> Foo : TransientLifetimeManager
    IFooDerived2 -> Foo : TransientLifetimeManager

这是正确的行为吗?有人能给出一些合乎逻辑的解释吗?我可以很容易地使用其他方法,我只是想了解为什么会发生这种情况。谢谢。

如果您将注册更改为以下内容:

container.RegisterType(typeof(IFooDerived1), typeof(Foo), new ContainerControlledLifetimeManager());
container.RegisterType(typeof(IFooDerived2), typeof(Foo), new TransientLifetimeManager());
container.RegisterType(typeof(IFoo), typeof(Foo), new ExternallyControlledLifetimeManager());
您将获得以下输出:

    IFoo -> Foo : ExternallyControlledLifetimeManager
    IFooDerived1 -> Foo : ExternallyControlledLifetimeManager
    IFooDerived2 -> Foo : ExternallyControlledLifetimeManager
沃特?无论检索什么抽象,都将得到相同的实例。所以,只要改变注册的顺序,你就会得到完全不同的生活方式

顺便说一句,
ExternallyControlledLifetimeManager
非常可怕,因为它使用了一个,并且可以在应用程序不再保留对它的引用后重新创建它。你几乎不应该使用这种生活方式

我正试图了解这一点,但在Unity中,当您进行注册时,您实际上是在以某种生活方式注册实现,并且提供的抽象只映射到该注册。因此,如果我们为Unity定义一个替代API,注册将变成这样:

MakeEntry(typeof(Foo), new ExternallyControlledLifetimeManager());
MapToEntry(from: typeof(IFoo), to: typeof(Foo));
因此,使用此“替代”API,可以更清楚地看到以下情况:

MakeEntry(typeof(Foo), new ExternallyControlledLifetimeManager());
MapToEntry(from: typeof(IFoo), to: typeof(Foo));
MakeEntry(typeof(Foo), new ExternallyControlledLifetimeManager());
MapToEntry(from: typeof(IFooDerived1), to: typeof(Foo));
MakeEntry(typeof(Foo), new TransientLifetimeManager());
MapToEntry(from: typeof(IFooDerived2), to: typeof(Foo));
这意味着同一个
Foo
有三个条目,显然Unity只是默默地接受这个条目,最后一个调用获胜。你不讨厌这种含蓄的行为吗


也许是时候切换到另一个库了?

除了这种令人担忧的统一行为之外,您可能还想看看您的设计,因为我认为您应该将
IFooDerived2
提供给您的行为提取到另一个实现中。新的
FooDerived2
实现依赖于
IFoo
。是的,你是对的,设计不是很好。我已经重新编写了“真实”代码。但我同意你的看法,这是一种“有趣”的行为。如果你为每个注册指定不同的名称,你也应该能够指定不同的LifetimeManager。请参阅“具有多个键的ContainerControlled LifetimeManager”部分。它还提到了您的问题(“具有多个接口的ContainerControlledLifetimeManager”),作者认为这种行为是一个bug(我倾向于同意)@thomasleveque,我知道:-)不。我发现这种行为非常有用。