Unity中的BuildUp方法不考虑MappingName

时间:2012-04-23 08:03:10

标签: unity-container

我对Unity BuildUp方法有一个奇怪的问题。我有一个映射到三个类的接口。我给每个映射命名了。

现在我需要在现有对象中注入依赖项(它是一个属性,因此我无法控制生命周期)。我调用BuildUp方法来注入依赖项,但它总是抛出一个异常,表示接口没有映射。

如果我只将接口映射到一个类型并删除映射名,则BuildUp方法可以正常工作。 如果我仅将接口映射到一个类型并指定映射名,则BuildUp方法将失败。 我已经尝试在配置和代码中注册类型而没有任何变化。

我怀疑这是一个错误,但我想知道是否还有其他人有想法。

这就是我称之为buildup方法的方法:

var newAttr = _container.BuildUp(myAttribute.GetType(), myAttribute, "Mapping1");

1 个答案:

答案 0 :(得分:1)

我尝试按照您的方案进行操作

var container = new UnityContainer();
container.RegisterType<IFoo, One>("1", new InjectionProperty("Bar", "1"));
container.RegisterType<IFoo, Two>("2", new InjectionProperty("Bar", "2"));
container.RegisterType<IFoo, Three>("3", new InjectionProperty("Bar", "3"));
One one = new One();
container.BuildUp(one.GetType(), one, "1");
Assert.AreEqual("1", one.Bar);

public interface IFoo
{
    string Bar { get; set; }
}
public class One : IFoo
{
    public string Bar { get; set; }
}
public class Two : IFoo
{
    public string Bar { get; set; }
}
public class Three : IFoo
{
    public string Bar { get; set; }
}

<强>更新

var container = new UnityContainer();
container.RegisterType<Person>(new InjectionProperty("Foo"));
container.RegisterType<IFoo, One>("1");
container.RegisterType<IFoo, Two>("2");
container.RegisterType<IFoo, Three>("3");
Person person = container.Resolve<Person>("1");
Assert.IsNotNull(person.Foo);
Assert.IsInstanceOfType(person.Foo, typeof(One));

public class Person
{
  public IFoo Foo { get; set; }
}

我想这就是你的意思?简短回答:这不是Unity工作的方式。

答案很长:你必须指定一个ResolverOverride为你做这件事。但即使这样也是不够的,因为您希望容器创建您想要为您注入的值。因此,您需要指定ResolvedParameter作为ResolverOverride的值。使用Unity的开箱即用部分Resolve看起来像这样

Person person = container.Resolve<Person>(new PropertyOverride("Foo", new ResolvedParameter(typeof(IFoo), "1")));

或者您可以使用此自定义覆盖

public class NamedPropertyOverride : ResolverOverride
{
  private readonly string propertyName;
  private readonly string registrationName;
  public NamedPropertyOverride(string propertyName, string registrationName)
  {
    this.propertyName = propertyName;
    this.registrationName = registrationName;
  }
  public override IDependencyResolverPolicy GetResolver(IBuilderContext context, Type dependencyType)
  {
    var currentOperation = context.CurrentOperation as ResolvingPropertyValueOperation;
    if (currentOperation != null && 
        currentOperation.PropertyName == this.propertyName)
    {
      Type propertyType = currentOperation
        .TypeBeingConstructed
        .GetProperty(currentOperation.PropertyName, BindingFlags.Instance | BindingFlags.Public)
        .PropertyType;
      return new NamedTypeDependencyResolverPolicy(propertyType, this.registrationName);
    }
    return null;
  }
}

将包含上述示例Resolve调用的行更改为此

Person person = container.Resolve<Person>(new NamedPropertyOverride("Foo", "1"));

这应该可以解决问题。