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?
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 A
s get injected)
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.