English 中文(简体)
Should I encapsulate my IoC container?
原标题:

Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.

I m trying to decide whether or not it makes sense to go through the extra effort to encapsulate my IoC container. Experience tells me that I should put a layer of encapsulation between my apps and any third-party component. I just don t know if this is bordering on overkill.

I can think of situations where I might want to switch containers. For instance, my current container ceases to be maintained, or a different container is proven to be more light-weight/performant and better fits my needs. If this happens, then I ll potentially have a lot of re-wiring to do.

To be clear, I m considering encapsulation of the registration and resolution of types. I think it s a no-brainer to encapsulate resolution - I d hope it s common practice to have a helper/util class delegating to the container.

EDIT:

The assumption is that I prefer to wire-up my types programmatically for type-safety, compile-time checking and refactorability. It s this code and its dependency on the container that I m looking to protect myself from.

I ve also been using an IoC container for several other projects that share a lot of the same relationships, but the container is a pain to work with so I want change. But, a change means I lose the reusability of the registration code. Hence, why I m contemplating encapsulation. It s not a huge burden, but one that I d, nevertheless, like to mitigate.

I m looking to:

  • Minimize the impact of change in containers / versions of containers
  • Provide some level of type-registration consistency across projects that may use different containers
  • Provide interface methods that make sense to me (RegisterSingleton<T,T> rather than RegisterType<T,T>( SomeLifetimeProvider ) - using Unity as an example).
  • Augment the container as conditions/scalability requirements change e.g. adding better caching, logging, etc during resolution/registration.
  • Provide my own model for registering type mappings.
    • Say I want to create a bunch of RegistrationHandler objects in an assembly/package and so I can easily segregate registration responsibilities across multiple classes and automatically pickup these handlers without changing code anywhere else.

I realize this is a bit subjective, so pros/cons might be helpful

Thanks!

最佳回答

Do it later, and only if you actually have the need to change IOC containers.

Pick an IOC container that is non-invasive. That is, one where the objects being connected to each other don t have any dependencies on the IOC container. In this case, there s nothing to encapsulate.

If you have to pick an IOC container that requires that you have dependencies on the container, choose one with the simplest dependencies/API you can. If you need to replace this IOC container (and you probably won t), implement adapters that bridge the new API to the old one.

In other words, let the first IOC container be the one that defines the interfaces for any future container so that you don t have to invent your own, and you can delay any of this sort of work until you absolutely need it.

EDIT:

I don t see a way of guaranteeing type-safety short of either:

  1. Designing a relatively complex implementation of the Builder pattern along with visitor implementations that would write IOC configuration files, or something equivalent.
  2. Implementing a type-safe IOC configuration DSL. (My choice if I had multiple apps that required swappable IOC containers.)
问题回答

It s best practice to do something only if there s an actual need for it, and never code something that you guess to be required sometimes in the future (that s the so-called YAGNI-principle). If your architecture is ok, you can easily change the container, if it actually should become necessary...

If you think you need this kind of flexibility, you may look at the Common Service Locator project at CodePlex. It does exactly what you look for: providing a common facade for various IoC containers.

HTH!

Rather than encapsulating the IOC container itself, I prefer to isolate the locus of interaction with the IOC container. For example, in ASP.Net MVC, I generally limit the exposure to the container to the controller factory and the global.aspx.cs file, where it s usually setup.

In my mind, having a lot of code that knows about the IOC container is an antipattern that increases complexity. I ve seen a fair amount of code in which objects feel free to ask the IOC container for their dependencies, and then they ve basically reduced the IOC container to a high-maintenance Service Locator.

Since IOC containers can resolve dependencies to an arbitrary degree of depth, it s pretty easy to make the controller factory the component that s responsible for involving the inversion of control containers. The constructor for each controller essentially specifies the services/repositories/gateways it needs.

For any of my apps, swapping the IOC container would essentially be a matter of rewriting the code the configures the container (specifies the bindings, etc.) and hooks up the controller factory. For apps exposed as services, the same basic idea should be reasonably manageable, though depending on the constraints of your runtime, you might have to use setter injection rather than constructor injection.





相关问题
C# - Design-related dispose question (take two)

I asked a question earlier today, but I think I need to approach it in a different way (on top of that there was a "hang up" in regards to DataSet). Here s a class that encapsulates the creation of a ...

object-private Vs class-private

Is there a notion of object-private in any OOP language ?? I mean more restrictive than the classic private access ? Private (or class-private) restricts the access to the class itself. Only methods ...

Unit testing opaque structure based C API

I have a library I wrote with API based on opaque structures. Using opaque structures has a lot of benefits and I am very happy with it. Now that my API are stable in term of specifications, I d like ...

Encapsulate other Apps in .Net MDI

Is it possible to encapsulate other windows apps in a .Net MDI form? The source code is not available for these apps... there s a set of programs we use that would be nice to have all wrapped into one ...

How to encapsulate a std::set properly?

I have a class named Particle which has a std::set as a member. The class looks like this: class Particle { private: std::set<vtkIdType> cells; std::set<vtkIdType>::iterator ipc; ...

Should I encapsulate my IoC container?

I m trying to decide whether or not it makes sense to go through the extra effort to encapsulate my IoC container. Experience tells me that I should put a layer of encapsulation between my apps and ...

热门标签