Problem configuring Windsor container based on Vendor
I'm fairly familiar with the whole concept of IoC/DI, but I've never implemented a solution before. This is my first time, so please feel free to give me a push in the right direction if you deem it necessary.
I've got multiple classes that implement the same Interface(IMyCustomFileReader
). I need to use one of these instances based on some Vendor information in my application. If the Vendor is Vendor1 I would like the IoC container to give me Vendor1FlatFileReader
and DummyClass1
when I request an instance of IMyCustomFileReader
and IDummyInterface
respectively.
Similarly I would like the container to return instances of XMLFileReader
and DummyClass2
when the Vendor is Vendor2.
I think (and let me know when I'm wrong) that I can use it using ChildContainers. At the moment my xml looks like this:
<components>
<component id="Vendor1"
service="SomeAssembly.IMyCustomFileReader, SomeAssembly"
type="SomeAssembly.Vendor1.Vendor1FlatFileReader, SomeAssembly.Vendor1">
</component>
<component id="Vendor1"
service="SomeAssembly.IDummyInterface, SomeAssembly"
type="SomeAssembly.DummyClass1, SomeAssembly">
</component>
<component id="Vendor2"
service="SomeAssembly.IMyCustomFileReader, SomeAssembly"
type="SomeAssembly.XMLFileReader, SomeAssembly">
</component>
<component id="Vendor2"
service="SomeAssembly.IDummyInterface, SomeAssembly"
type="SomeAssembly.DummyClass2, SomeAssembly">
</component>
</components>
This configuration is erroneous as I cannot have multiple components with the same id element - Not even when the Interfaces are different like in the above example. I was hoping I could do something like Container.Resolve<IMyCustomFileReader>("Vendor1")
, then when an instance of IMyCustomFileReader
is requested and the key
value is Vendor1 I would get back an instance of Vendor1FlatFileReader
.
I get a Castle.MicroKernel.ComponentRegistrationException
when I try to do it this way.
Something else I think might work is the concept of ChildContainers, but how would I go about configuring those in xml?
Also, I would prefer not to give my c开发者_开发技巧omponents names like Vendor1_IMyCustomFileReader
and Vendor2_IMyCustomFileReader
. I would also prefer to have only 1 configuration file and not separate ones for each Vendor (if possible). Has anyone else encountered a similar problem before? How can I solve this?
Yes, component ids must be unique. I wouldn't recommend child containers unless you really know what you're doing. In this case, it looks like you're trying to do some sort of multi-tenancy, so I recommend taking a look at handler selectors, this will let you select the appropriate component based on the "vendor" without resorting to service location (if you do container.Resolve() in application-level code, you already lost).
Would you be willing to use the fluent registration API? If so, you could decide which components to register at runtime based on the "vendor" (the registrations for each vendor could live in a separate IWindsorInstaller implementation). This solution assumes you know which "vendor" to use at start-up and that the "vendor" will not change throughout the lifetime of the application (I'm guessing that is a valid assumption based on how you stated the question). You could take a similar approach with XML configuration, but you would need to separate the configuration for each vendor into separate config files, and you say you are opposed to that -- could you clarify why?
Please comment and let me know if you think that the fluent API approach could work, and I'd be happy to post an example.
精彩评论