gpt4 book ai didi

c# - 固件 : Unexpected result upon unnamed registration of the same mapTo with different mapFrom with injectedProperties

转载 作者:行者123 更新时间:2023-11-30 18:22:26 28 4
gpt4 key购买 nike

在将相同的具体类注册到不同的未命名实例时,我们看到 Unity 出现意外行为。在这种情况下,注册似乎以意想不到的方式相互干扰。

  • 我们为我们想要注入(inject)的其他应用程序提供了一个框架不同的界面(即对一个共同概念的不同看法)可能以不同方式初始化的同一个类,使用不同的注入(inject)参数和/或不同的值。当框架通过一个接口(interface)使用类时,它可以期望与通过 a 使用类时的行为可能不同不同的接口(interface)。因此我们注册了两个接口(interface)具有不同初始化的相同 mapTo 类(并且可能lifetimes)。合乎逻辑的是,当我们注册类型时Unity 中的不同接口(interface),它们不会相互干扰其他。这适用于命名实例,但不适用于未命名实例实例。
  • 尝试的三个合乎逻辑的结果注册映射到同一类的不同接口(interface):
    1. 异常:在第二次注册期间应该抛出异常。仅当我们认为这是对框架的滥用时才会出现异常;我们不相信这是真的。
    2. 覆盖:覆盖可能有意义,但当前实现的内部表示似乎暗示它不是为了覆盖而设计的,因为 mapTo 类型的参数增加了。在下面的示例代码中,我们注册了 2 个映射到同一个类的不同接口(interface),每个接口(interface)都注入(inject)了 2 个属性。我们可以看到 container.policies.policies(类型为 ObjectBuilder.SpecifiedPropertiesSelectorPolicy)propertiesAndValues 的值包含 4 个注入(inject)属性。在覆盖的情况下,我们预计会看到 2 个注入(inject)的属性使用第二次注册的值进行了初始化。在注册映射到同一类型的几个不同类型的情况下,此行为的结果将在每个属性中注入(inject)一些具有值的属性,而其中一些则没有(预计未初始化),已解析的实例将不会正确初始化任何注册类型。
    3. 独立注册:所有注册都将被正确解析,每个注册都将被注入(inject)正确的属性值。

独立注册是我们所期望的,但不起作用。似乎 mapTo 类型不是根据注册类型进行管理,而是仅根据 mapTo 类型和注册名称进行管理。我们想了解预期的行为是什么,当前的行为是否符合预期,以及是否有一种干净的方法来实现独立注册。请注意,我们已经看到了命名注册的建议,但我们不想更改我们的框架,因为它正在使用中,而且通常我们不想无缘无故地强制应用程序符合命名实例。附加的代码演示了意外行为。

    using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace TestUnity
{
public interface IBaseInterface
{
string BaseString { set; get; }
}

public interface IChildInterface : IBaseInterface
{
string ChildString { set; get; }
}

public class ChildClass : IChildInterface
{
public string BaseString { set; get; }
public string ChildString { set; get; }
}

public class ContainerClass
{
public IBaseInterface impl { set; get; }
}

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

// the expected result BaseString ="IBaseInterface_BaseString" & ChildString ="IBaseInterface_ChildString"
// the result is BaseString ="IChildInterface_BaseString" & ChildString ="IChildInterface_ChildString"
var iBaseInterface = container.Resolve<IBaseInterface>();

// the expected result BaseString ="IChildInterface_BaseString" & ChildString ="IChildInterface_ChildString"
var iChildInterface = container.Resolve<IChildInterface>();

//We expect test class will be initialize with BaseString ="IBaseInterface_BaseString" & ChildString ="IBaseInterface_ChildString"
//but the result is the expected result BaseString ="IChildInterface_BaseString" & ChildString ="IChildInterface_ChildString"
var testClass = container.Resolve<ContainerClass>("Test");

//The container.Registrations include both regestered types(IBaseInterface & IChildInterface)
foreach (var registration in container.Registrations)
{
Console.WriteLine(@"RegisteredType :{0} ,MappedToType :{1}", registration.RegisteredType, registration.MappedToType);
}
Console.ReadLine();
}
}
}

应用程序配置

    <?xml version="1.0"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IBaseInterface" type="TestUnity.IBaseInterface, TestUnity" />
<alias alias="IChildInterface" type="TestUnity.IChildInterface, TestUnity" />
<alias alias="transient" type="Microsoft.Practices.Unity.TransientLifetimeManager, Microsoft.Practices.Unity"/>
<container>

<register type="IBaseInterface" mapTo="TestUnity.ChildClass, TestUnity">
<lifetime type="transient"/>
<property name="BaseString" value="IBaseInterface_BaseString" />
<property name="ChildString" value="IBaseInterface_ChildString" />
</register>

<register type="IChildInterface" mapTo="TestUnity.ChildClass, TestUnity">
<lifetime type="transient" />
<property name="BaseString" value="IChildInterface_BaseString" />
<property name="ChildString" value="IChildInterface_ChildString" />
</register>


<register name="Test" type="TestUnity.ContainerClass, TestUnity" mapTo="TestUnity.ContainerClass, TestUnity">
<lifetime type="transient" />
<property name="impl" dependencyType="IBaseInterface" />
</register>

</container>
</unity>
</configuration>

最佳答案

TL;DR - 抱歉,这似乎是 Unity 的一个限制。


我不是构建 Unity 的团队的成员,因此我只能推测预期的行为,因为没有针对此特定场景明确记录。但是优先考虑 Unity 的其他行为,我预计它会覆盖之前注册的 InjectionProperty

您是正确的,对象构建器在查找用于构建请求解析的对象实例的策略时不考虑已注册的类型。对象生成器键由 mapTo 类型和名称组成(参见 NamedTypeBuildKey )。创建此键的方式是 Unity 对象生成器内部不可或缺的一部分。尝试将已注册的类型添加到管道中的此键将比您想要处理的自定义更多。而且我想不出另一种方法来引入您希望的基于注册类型的独立注册行为(除了不同的具体类或多个命名注册)。

关于c# - 固件 : Unexpected result upon unnamed registration of the same mapTo with different mapFrom with injectedProperties,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33949079/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com