Finally started to conf开发者_开发技巧igure an IoC Container!
I'm using Unity and have configured it to have my objects registered using the config file:
e.g.
<container>
<register type="ILogger" mapTo="Logger">
<lifetime type="singleton"/>
</register>
<register type="IPdfWriter" mapTo="PdfWriter">
<lifetime type="perthread" />
<constructor />
</register>
</container>
I've reached a point where I doubt this is a good approach to register types.
For example a class of mine is dependent on the ICacheManager from Microsoft Enterprise Library Caching block and the below should be injected to it:
EnterpriseLibraryContainer.Current.GetInstance<ICacheManager>()
and that doesn't seem to be possible using just unity config settings.
It seems to me that always it's better to register the types using code rather than the config file.
What's your experience/advise in this?
Thanks
The answer is - do you think you'll need to change the configuration after deployment? If so, use the config file. If not, I find doing it in code to be easier.
And to answer the question you didn't ask - what you want to do is in fact possible, and quite easy. The trick is to use the same container instance for Enterprise Library and for everything else. In your startup code, set up your Unity container instance, and add the EnterpriseLibraryCoreExtension to it (which you can do in config). Then set that container as your EnterpriseLibraryContainer.Current. Once you've done that, you can have a type with a dependency on ICacheManager and everything else will just work.
Something like this:
In XML config:
<unity>
<namespace name="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity" />
<assembly name="Microsoft.Practices.EnterpriseLibrary.Common" />
<container>
<extension type="EnterpriseLibraryCoreExtension" />
<register type="IMyType" mapTo="MyImplementation">
<constructor>
<param name="cacheManager" />
</constructor>
</register>
</container>
</unity>
(You will of course need your entlib configuration as well).
Then in the startup of your application, have code like this:
var container = new UnityContainer()
.LoadConfiguration();
EnterpriseLibraryContainer.Current = new UnityServiceLocator(container);
From there everything should just work. EnterpriseLibraryContainer.Current will get objects from your container, and objects resolved from the container will get entlib objects injected like any other dependency.
Once you've gone this step, the next one is to get all your entlib objects via DI and drop the explicit calls to EnterpriseLibraryContainer.Current.
Some good answers so far.
There is a third option: use both. When you configure the same thing twice, the second definition over-writes the first. That means you can configure a set of reasonable defaults in code at design time and then load runtime updates from xml.
Also remember that Attributes on classes are an option for defining interception call handlers. This can remove that whole section from your policies whether xml or C#.
In my experience, using C# is way more expressive and dynamic than xml. However, there are parts of the setup that you may want to be able to change at runtime, then you can do both. You can use both config and code to setup the container.
If you expect to be switching out component implementations on a production machine (such as a client's web server) then you should be using a configuration file.
If you are just using Unity to make testing easier/reduce or remove dependencies and don't expect to be changing out parts on a production machine, then spinning it up in code is fine.
As others have said : using the config approach makes the code massively flexible in terms of switching types without a code change.
The downside is leaving yourself open to typos that take a while to trace if you have a large set of registrations. Every now and then I often see a fat fingered developer mistype a class name and this leads to a good thirty minutes or so of head scratching!
Personally having used both approaches I prefer the coding convention. But if I was on a project that really really needed to be dynamic then go configuration!
精彩评论