I'm trying to learn how to use Castle Windsor IoC, and I'm having some difficulty understanding how to configure some of the objects that I need for a dynamic solution. Basically, I have several IDataSource implementations, and I need to choose an implementation to use based on how a particular "data source" is configured. Therefore, I could have quite a few data sources configured to use one of three implementations. My expectation is that the dependent code will depend on the factory method, which will provide them with the correct IDataSource when it is provided with a “data source identifier” along with the dependencies required by the IPrincipal implementation.
I am struggling with the correct way to write a registration delegate for Windsor. Below is about what I have. I am trying to use a method DynamicParameters(which may turn out to be wrong to use) to execute a logic that determines which implementation to use and then calls Resolveto pull this particular version. But I don’t know how to return the allowed object, since it DynamicParametersexpects ComponentReleasingDelegate, which, as I suppose, means that it should be something like return k => { k.ReleaseComponent(dataSource); }. But then how can I provide the data source that I received back to the container so that it returns to the caller?
struct DataSourceInfo {
string Id;
string ProviderType;
}
interface ICatalog : IDictionary<string , DataSourceInfo> {
}
class Catalog : ICatalog {
}
interface IDataSource { }
class Source1 : IDataSource {
Source1(string id, IPrincipal principal) { }
}
class Source2 : IDataSource {
Source2(string id, IPrincipal principal) { }
}
container.Register(Component.For<ICatalog>().LifeStyle.Singleton.ImplementedBy<Catalog>());
container.Register(Component.For<IDataSource>().LifeStyle.Transient
.DynamicParameters((kernel, context, args) => {
if (args == null || !args.Contains("id") || !(args["id"] is string)) throw ApplicationException("bad args");
var id = (string)args["id"];
var catalog = kernel.Resolve<ICatalog>();
DataSourceInfo info;
try { info = catalog[id]; } finally { kernel.ReleaseComponent(catalog); }
var dataSource = kernel.Resolve<IDataSource>(info.ProviderType, args);
});
container.Register(Component.For<IDataSource>().LifeStyle.Transient.ImplementedBy<Source1>().Named("Source1"));
container.Register(Component.For<IDataSource>().LifeStyle.Transient.ImplementedBy<Source2>().Named("Source2"));
class AppConfigurer {
AppConfigurer(ICatalog catalog) {
catalog["sourceA"] = new DataSourceInfo() { Id = "sourceA", ProviderType = "Source1" };
catalog["sourceB"] = new DataSourceInfo() { Id = "sourceB", ProviderType = "Source2" };
catalog["sourceC"] = new DataSourceInfo() { Id = "sourceC", ProviderType = "Source2" };
catalog["sourceD"] = new DataSourceInfo() { Id = "sourceD", ProviderType = "Source2" };
catalog["sourceE"] = new DataSourceInfo() { Id = "sourceE", ProviderType = "Source1" };
}
}
class Dependant {
Dependant (Func<string, IPrincipal, IDataSource> factory) {
var sourceA = factory("sourceA", somePrincipal);
var sourceB = factory("sourceB", somePrincipal);
var sourceC = factory("sourceC", somePrincipal);
}
}
: DynamicParameters UsingFactoryMethod , . , , , container.ResolveAll(), factory, , .