上一讲介绍了DDD中的领域层,并提到下次要讲Unity,所以这篇文章当然就要介绍它了,呵呵,Unity是Microsoft.Practices中的一部分,主要实现了依赖注入的功能,或者叫它控制反转,对于控制反转(IoC)的文章我介绍了不少,Autofac,Castle等等,今天主要说一下Unity!
在我的DDD架构项目中,各层间实现IoC使用的是Unity,因为考虑到AOP,cache等功能,所以就直接用Microsoft.Practices组件了,它真的很强大!这次的项目在业务上采用WCF实现,所以WCF业务与基础设施之间会有通信,而基础设施只是去实现Domain定义的功能,所以这两个层之间也会有通信,最后就是Domain与WCF之间同样存在着接口的通信,如图:
Domain层定义一个接口,部分代码如下:
/// <summary> /// 获取产品列表 /// </summary> /// <returns></returns> IQueryable<Product> GetProduct();
基础设施层实现它
public IQueryable<Product> GetProduct() { return this.GetModel(); }
它们之间的通信不存在IoC,因为如果你要使用其它的持久化方法,可以再建立一个项目,以别一种方式去实现持久化
WCF去声明一个Domain层的接口,实例化它的基础设施层的实例,这个过程需要解耦合,我们使用Unity来实现,它需要我们在config中去定义如何去实例化。
public class ProductServiceImpl : IProductService { private readonly IProductRepository _productRepository; /// <summary> /// 构造方法注入 /// </summary> /// <param name="productRepository"></param> public ProductServiceImpl(IProductRepository productRepository) { if (productRepository == (IProductRepository)null) throw new ArgumentException("context can't is null."); _productRepository = productRepository; } #region IProductService 成员 public ProductDTO GetProductByID(int id) { Mapper.CreateMap<Product, ProductDTO>(); return Mapper.Map<Product, ProductDTO>(_productRepository.Find(id)); } }
上面使用unity中的构造方法注入,我们还可以使用服务调度器进行注入,看这种代码
public class ProductService : ServiceBase, IProductService { //通过ServiceLocator从IoC容器中获得对象 IProductService _productService = ServiceLocator.Instance.GetService<IProductService>(); #region IProductService 成员 public ProductDTO GetProductByID(int id) { return _productService.GetProductByID(id); } }
下面是配置文件中需要注入的代码片断,包括缓存模块和日志模块
<configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" /> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> <section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </configSections> <!--BEGIN: Unity--> <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" /> <container> <extension type="Interception" /> <register type="Project.Caching.ICacheProvider, Project.Caching" mapTo="Project.Caching.EntLibCacheProvider, Project.Caching" /> <!--对数据上下文的注入--> <register type="DDD_AOP_WCF.Domain.Products.IProductRepository, DDD_AOP_WCF.Domain" mapTo="DDD_AOP_WCF.Infrastructure.Repository.ProductRepository, DDD_AOP_WCF.Infrastructure" /> <!--对WCF的访问进行的注入与缓存和异常的拦截--> <register type="DDD_AOP_WCF.ServiceContracts.IProductService, DDD_AOP_WCF.ServiceContracts" mapTo="DDD_AOP_WCF.Service.Implements.ProductServiceImpl, DDD_AOP_WCF.Service"> <!-- <interceptor type="VirtualMethodInterceptor" />--> <interceptor type="InterfaceInterceptor" /> <interceptionBehavior type="Project.InterceptionBehaviors.CachingBehavior, Project.InterceptionBehaviors" /> <interceptionBehavior type="Project.InterceptionBehaviors.ExceptionLoggingBehavior, Project.InterceptionBehaviors" /> </register> </container> </unity> <!--END: Unity--> <!--BEGIN: Caching--> <cachingConfiguration defaultCacheManager="ByteartRetailCacheManager"> <cacheManagers> <add name="ByteartRetailCacheManager" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" expirationPollFrequencyInSeconds="600" maximumElementsInCacheBeforeScavenging="1000" numberToRemoveWhenScavenging="10" backingStoreName="NullBackingStore" /> </cacheManagers> <backingStores> <add type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="NullBackingStore" /> </backingStores> </cachingConfiguration> <!--END: Caching-->
<!--BEGIN: log4net-->
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="log.log"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="100KB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%newline%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
<logger name="ByteartRetail.Logger" >
<!--control log level: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
<!--如果没有定义LEVEL的值,则缺省为DEBUG-->
<level value="INFO"/>
<appender-ref ref="RollingFileAppender"/>
</logger>
</log4net>
<!--END: log4net-->
好了,对于Unity在DDD中的使用就介绍到这里,如有不清楚的地方,可以直接给我留言或发email!