DDD~Unity在(zai)DDD中的使用
上一講介紹了DDD中的領域層,并提到下次要講Unity,所以這篇文章當然就要介紹它了,呵呵,Unity是Microsoft.Practices中的一部分,主要實現了依賴注入的功能,或者叫它控制反轉,對于控制反轉(IoC)的文章我介紹了不少,Autofac,Castle等(deng)(deng)等(deng)(deng),今天主要說一下Unity!
在我的(de)(de)(de)DDD架(jia)構項目(mu)中,各層間(jian)實現(xian)IoC使(shi)用(yong)的(de)(de)(de)是(shi)(shi)Unity,因為(wei)考慮(lv)到(dao)AOP,cache等功能,所以(yi)(yi)就直接用(yong)Microsoft.Practices組件(jian)了(le),它(ta)真(zhen)的(de)(de)(de)很強(qiang)大!這次(ci)的(de)(de)(de)項目(mu)在業(ye)務上(shang)采用(yong)WCF實現(xian),所以(yi)(yi)WCF業(ye)務與基(ji)礎設(she)施之間(jian)會(hui)(hui)有通信,而基(ji)礎設(she)施只(zhi)是(shi)(shi)去實現(xian)Domain定(ding)義的(de)(de)(de)功能,所以(yi)(yi)這兩個層之間(jian)也會(hui)(hui)有通信,最后就是(shi)(shi)Domain與WCF之間(jian)同樣(yang)存在著接口(kou)的(de)(de)(de)通信,如(ru)圖:
Domain層定義一個(ge)接口,部分代碼如下(xia):
/// <summary> /// 獲取(qu)產品列表(biao) /// </summary> /// <returns></returns> IQueryable<Product> GetProduct();
基礎設施層實現它
public IQueryable<Product> GetProduct() { return this.GetModel(); }
它(ta)們(men)之(zhi)間的通信不(bu)存在IoC,因(yin)為如果你要使用(yong)其它(ta)的持(chi)久化方法,可以(yi)再建(jian)立一個項目,以(yi)別一種(zhong)方式去實現持(chi)久化
WCF去(qu)聲明(ming)一個(ge)Domain層的(de)接口,實(shi)例化它的(de)基礎設(she)施層的(de)實(shi)例,這個(ge)過(guo)程(cheng)需(xu)(xu)要解耦合(he),我(wo)們使用Unity來實(shi)現,它需(xu)(xu)要我(wo)們在config中(zhong)去(qu)定義如何去(qu)實(shi)例化。
public class ProductServiceImpl : IProductService { private readonly IProductRepository _productRepository; /// <summary> /// 構造(zao)方法注入 /// </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中的(de)構造方法注(zhu)(zhu)入,我們還可以使用服(fu)務調度(du)器進(jin)行注(zhu)(zhu)入,看這種代碼(ma)
public class ProductService : ServiceBase, IProductService { //通過ServiceLocator從IoC容器中獲得對象(xiang) IProductService _productService = ServiceLocator.Instance.GetService<IProductService>(); #region IProductService 成員 public ProductDTO GetProductByID(int id) { return _productService.GetProductByID(id); } }
下面(mian)是配置(zhi)文件中需要注入的(de)代碼片斷,包括緩存模塊和日志模塊
<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="//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中的(de)使用就介紹(shao)到這里,如有(you)不(bu)清楚的(de)地方,可以直(zhi)接給我留言(yan)或(huo)發(fa)email!