我们看到Unity在向不同的未命名实例注册相同的具体类时会出现意外行为。在这种情况下,注册似乎以意想不到的方式相互干扰。
独立注册是我们所期望的,但不起作用。似乎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();
}
}
}
的App.config
<?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>
答案 0 :(得分:0)
TL; DR - 抱歉,但这似乎是对Unity的限制。
我不是构建Unity的团队成员,因此我只能推测预期的行为,因为没有明确记录此特定方案。但是,优先考虑Unity的其他行为,我原以为它会覆盖以前的注册InjectionProperty
。
在查找用于构建请求解析的对象实例的策略时,对象构建器不会考虑注册类型。对象构建器键由mapTo类型和名称组成(请参阅NamedTypeBuildKey)。创建此密钥的方式是Unity对象生成器内部的组成部分。尝试将注册类型添加到管道中的此键将比您想要解决的更加自定义。而且我无法想到另一种方式来根据注册类型(除了不同的具体类别或多个命名注册)引入您期望的独立注册行为。