Castle Windsor Map Named Component To Specific Pro

2019-07-20 16:14发布

问题:

Following scenario:

We use the Fluent API to register all components in an assembly and two components tyepof(A) with named keys. Another class B with two properties typeof(A) should get the named components injected.

Sample:

public class A : IA {}

public class B : IB
{
    [Named("first")]
    public IA First { get; set; }

    [Named("second")]
    public IA Second { get; set; }
}

// ...

container.Register(Component.For<IA>().Instance(new A(value1)).Named("first"));
container.Register(Component.For<IA>().Instance(new A(value2)).Named("second"));

// ...
var b = container.Resolve<IB>(); // named instances of A get injected to B using the Named attribute

Is this possible with an attribute like Named or only with the Xml Config?

回答1:

The standard way to do this in Windsor is using service overrides. In your example, when you register B you'd do it like this:

container.Register(Component.For<IB>().ImplementedBy<B>()
                     .ServiceOverrides(new {First = "first", Second = "second"}));

(there are other ways to express this, check the linked docs)

Using a Named attribute as you propose pollutes the code with unrelated concerns (B should not care about what As get injected)



回答2:

Here's how you would solve this problem using DependsOn and incorporating the nameof expression (introduced in C# 6.0):

container.Register
(
    Component.For<IA>()
        .Instance(new A(value1))
        .Named("first"),
    Component.For<IA>()
         .Instance(new  A(value2))
         .Named("second"),
    Component.For<IB>()
          .ImplementedBy<B>()
          .DependsOn
          (
              Dependency.OnComponent(nameof(B.First), "first"),
              Dependency.OnComponent(nameof(B.Second), "second")
          )      
)

Dependency.OnComponent has many overrides, but in this case the first parameter is the property name, and the second parameter is the component name.

See here for more documentation.