Im fairly new with DDD and Im trying to use IOC in order to loosen up my tightly coupled layers :)
My C# web application consists of a UI, domain and persistence layer. My persistence layer references my domain layer and contains my concrete repository implementations and nhibernate mappings. Currently my UI references my domain layer.
My question : How do I use an IOC container to inject my concrete classes, in my persistence layer, into my domain layer? Does this meen that my U开发者_如何学运维I should also reference my persistence layer?
Dave is right, the purpose of DI and IOC is to loosely couple the components of your system.
Your UI should only know about your Domain, your Domain should only know about your Persistence, and your Persistence should know nothing about anyone else.
Good .NET IoC containers are StructureMap (my preferred), Ninject and Castle Windsor.
There are multiple ways of implementing DI/IoC, the most preferred way is using interfaces.
You would have an interface for your Persistence layer:
public interface IPersistantStorage
{
List<Foo> GetStuff();
void AddStuff(Foo f);
}
Likewise for your Domain layer:
public interface IDomainManager
{
List<Foo> GetStuff();
void AddStuff(Foo f);
}
Then implement concrete classes for each.
Your chosen IoC container will then "inject" the concrete classes to the constructor.
Here's an example of how it works with StructureMap:
public class SomeClassInUILayerThanNeedsToGetSomeThing
{
IDomainManager domain;
public SomeClassInUILayerThanNeedsToGetSomeThing(IDomainManager realDomain)
{
this.domain = realDomain;
}
public List<Foo> GetSomethingFromSomewhere()
{
return domain.GetStuff();
}
}
Then in the StructureMap bootstrapper (called usually in your application start event - Global.asax)
public static void ConfigureIoCFramework()
{
ObjectFactory.Initialize(x =>
{
x.For<IDomainManager>().Use<DomainManager>();
x.For<IPersistantStorage>.Use<NHibernateStorage>();
});
}
All your UI knows is that its going to call some Domain class that implements some interface. All your Domain knows is that its going to call some Persistence class that imlplements some interface.
The "How" or this "What" is handled by the DI Container above.
How you setup what depends on your system. I typically have this setup:
- Website -> references 2 assemblies: Common (extension methods, business entities, etc), Service (like a calling point from UI - layers on caching to persistence storage, etc)
- Service -> references 1 assembly: Repository
- Repository -> references nothing.
Then i would inject a concrete implementation of a service layer into the UI, and inject a concrete implementation of the repository into the Service layer.
If you then look at your solution properties, look at the Web project, you will only see 2 depedencies. In particular, it will not depend on the persistence layer.
If you want to pass around objects, consider projecting your tables into POCO's (contained in the Common assembly).
No, I wouldn't inject persistence into either model or view.
You really need a separate service tier that sits between view and the rest. The service tier knows about units of work; it orchestrates persistence and model objects to fulfill the use cases.
Model objects need not know about what layer uses them. They express the domain concepts.
You UI should NOT reference your persistence layer. Using IoC, you would inject the concerns of the lower layer up into the layer above it, in a "stack" arrangement.
So, your IoC configuration will inject the persistence implementation into your domain layer. The domain layer should have no knowledge of persistence except for the interfaces used to save and retrieve domain objects. Those interfaces are implemented by the classes /logic in your persistence layer.
精彩评论