I have class that has dependency on string:
public class Person
{
private readonly string _name;
public Person(string name)
{
if (name == null) throw new ArgumentNullException("name");
_name = name;
}
}
This string 'name' is known only at runtime, eg. it is defined in configuration. So I have this interface that provides this string:
public interface IConfiguration
{
string Name { get; }
}
Both types, Person and IConfiguration (with its implementation which is not important here) are registered with Windsor container.
Question: how can I tell WindsorCastle container that it should inject the Name property of IConfiguration to the constructor of Person class?
Caveat: I don't want to inject IConfiguration to Person class or use typed factories... the Person class must be simple and accept only string as parameter.
There are probably more ways to do this since Windsor is ridiculously flexible, but here are three off the top of my head:
If IConfiguration
is a singleton or somehow can populate Name
without any other assistance, you could do the following:
container.Register(Component.For<IConfiguration>().ImplementedBy<Configuration>());
container.Register(Component
.For<Person>()
.DynamicParameters((DynamicParametersDelegate)ResolvePersonName));
// This should be a private method in your bootstrapper
void ResolvePersonName(IKernel kernel, IDictionary parameters)
{
parameters["name"] = kernel.Resolve<IConfiguration>().Name;
}
This method is invoked before resolving the Person
, and is setting the name
key/value pair to be the desired value. Windsor then uses this dictionary to override any dependencies in the constructor. I'd probably just make it a lambda to be terser:
.DynamicParameters((k,p) => p["name"] = k.Resolve<IConfiguration>().Name));
If the Name
value is actually defined in the applications settings file, Windsor has a built-in option for that:
container.Register(
Component.For<Person>()
.DependsOn(Dependency.OnAppSettingsValue("name", "configSettingKeyName")));
You say you don't want to use Typed Factories, but I think this is a reasonable siutation for using one. It wouldn't complicate the Person
class at all, but it would add a bit to the code creating the Person
objects (people?). Here's an example:
Define the factory interface:
public interface IPersonFactory
{
Person Create(string name);
}
Then where you are creating your Person
, inject the factory and use that instead:
public class PersonUser
{
public Personuser(IConfiguration configuration, IPersonFactory personFactory)
{
Person person = personFactory.Create(configuration.Name);
}
}
You'll have to add the facility and register the interface, but it's easy:
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IPersonFactory>().AsFactory());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With