How to understand the rule: "Store in IoC container only services. Do not store any entities."
The rule "Store in IoC container only services. Do not store any entities." I've found in that blog and it have a lot of supporters.
There are also sample of the class constructor:
MyClass(ILog log,
IAudit audit,
IPermissions permissions,
IApplicationSettings settings) {/*..*/}
where MyClass was announced as entity that should not be stored in the container.
So "IoC ready service" can't depend on infrastructure .. services.
But now I completely do not understand how "IoC people" work with "real code". Service in C# still will be developed as a class, and that class usually depends on class that encapsulate logging, rarely depends on the class that encapsulate custom exception handling (e.g. converting unhandled Exception to FaultContract) etc. ...
I see some ways: May be they just do not declare those infrastructure dependencies? Use them as functionality available form static methods?
Or may be "IoC supporters" think that "IoC ready" service should publish log/trace/authenticate/handleException events as a part of service contract (and then yes - - there are no "dependencies on infrastructure")? But also that means that such service should be duplex (to post log events)...
May be theirs "services" are only proxies? Proxy do not have dependencies on infrastructure because of all infrastructure is remote, but I'm not happy to found that IoC container should be used to store only proxies. Am I right in my disappointment? But then what about MS Enterprise Library that is designed to sore loggers and handlers in the Unity container?
APPEND:
I understand it that way: there are services (with contracts), there are entities (business), and there are infrastructure stuff LogWriter, AuthenticationProvider;- creating/hosting service I initiate it with some infrastructure stuff (so I am publishing dependencies on infrastructure not on entities). What I sti开发者_运维问答ll do not understand am I right in that or not?
APPEND 2:
After discussion I understand situation that way. ILog, etc - are services (even if they are infrastructure services) and therefore if the "MyClass" is the realization of the some service then rule is not violated. That means rule is good but sample is bad.
One problem left: I still do not understand the opposition of entities and services in one sentence without explanation. They are from different conceptual layers: 1) services-messages; and 2)business rules-entities.. So possibly first I should adopt new terminolgy.
Short answer: entities should not depend on services! This is a huge part of the "inversion" part of dependency inversion. As stated in the post you linked to:
I found the design of the question example is wrong in a sense that an entity (which MyClass is) should NOT have dependencies on infrastructure (or any other) services.
MyClass
, in your example, depends on three cross-cutting concerns, plus IApplicationSettings
. The cross-cutting concerns should be introduced using AOP/dynamic proxy techniques, or pubsub-style events if you prefer. And MyClass
should be injected with settings specific to its functionality by whatever service is in charge of creating instances of it. For example, PersonFactory
could be injected with IApplicationSettings
, then create Person
objects, passing appSettings.SomePersonRelatedSetting
into the Person
constructor.
The rule "Store in IoC container only services. Do not store any entities." means that you should register in IoC container pair interace
- implementation
. This rule is a result of dependency inversion principle. According to your example this means that you should extract public interface from your MyClass
and use it instead of MyClass implementation.
The rule that says
"Store in IoC container only services. Do not store any entities."
is talking from conceptual perspective and not from implementation perspective. Conceptually, entity represents data (or state) and perhaps data related rules (as methods). Service represents functionality exposed via published contract and generally, state-full services is not a good idea. So although C# class
construct would be used to represent both service implementation and entity implementation - what this rule is saying is that only services should be put into IoC. IoC really acts as a configurable super-flexible factory that provides correct service implementation for the required service contract. Again, one can have pattern such as ActiveRecord
where perhaps data and persistence functionality are merged - I as such don't like the pattern but there are many followers and typical usage would put such entities into IoC container. However, important difference would be probably the entity would be registered against some contract (and not implementation)
Again note that your code has dependencies on service contracts and not on specific service implementation. Now, dependencies can be exposed and resolved in multiple ways. You can mark dependencies by putting them as constructor parameters OR as public property getter/setter OR using declarative syntax such as attributes. These are typically resolved automatically by DI framework. However, you can always get/resolve some service by making explicit call such as ILog log = DIContainer.Get<ILog>();
. So as far as Infrastructure services goes, I think that what the blog author is saying is that don't mark infrastructure services as explicit dependencies (by constructor args or properties etc). You can resolve them using code (as quoted above) or perhaps using simple singleton helpers etc. In a way, he is right because one can always assumes that every service/class depends on infrastructure and so dependencies need not be stated using public API.
精彩评论