Dave 是对的,DI 和 IOC 的目的是松散耦合系统的组件。
您的 UI 应该只知道您的域,您的域应该只知道您的 Persistence,而您的 Persistence 不应该知道其他任何人。
良好的 .NET IoC 容器是 StructureMap(我的首选)、Ninject 和 Castle Windsor。
有多种实现 DI/IoC 的方式,最首选的方式是使用接口。
你会有一个持久层的接口:
public interface IPersistantStorage
{
List<Foo> GetStuff();
void AddStuff(Foo f);
}
同样适用于您的域层:
public interface IDomainManager
{
List<Foo> GetStuff();
void AddStuff(Foo f);
}
然后为每个实现具体的类。
然后,您选择的 IoC 容器会将具体类“注入”到构造函数中。
这是一个如何使用 StructureMap 的示例:
public class SomeClassInUILayerThanNeedsToGetSomeThing
{
IDomainManager domain;
public SomeClassInUILayerThanNeedsToGetSomeThing(IDomainManager realDomain)
{
this.domain = realDomain;
}
public List<Foo> GetSomethingFromSomewhere()
{
return domain.GetStuff();
}
}
然后在 StructureMap 引导程序中(通常在您的应用程序启动事件中调用 - Global.asax)
public static void ConfigureIoCFramework()
{
ObjectFactory.Initialize(x =>
{
x.For<IDomainManager>().Use<DomainManager>();
x.For<IPersistantStorage>.Use<NHibernateStorage>();
});
}
您的 UI 所知道的是,它会调用一些实现某些接口的域类。
您的域所知道的是,它会调用一些实现某些接口的 Persistence 类。
“如何”或这个“什么”由上面的 DI 容器处理。
如何设置取决于您的系统。我通常有这样的设置:
- 网站 -> 引用 2 个程序集:通用(扩展方法、业务实体等)、服务(如 UI 中的调用点 - 缓存层到持久性存储等)
- 服务 -> 引用 1 个程序集:存储库
- 存储库 -> 不引用任何内容。
然后我会将服务层的具体实现注入 UI,并将存储库的具体实现注入服务层。
如果您随后查看解决方案属性,再查看 Web 项目,您只会看到 2 个依赖项。特别是,它不会依赖于持久层。
如果您想传递对象,请考虑将表投影到 POCO(包含在 Common 程序集中)。