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).