基於Enterprise Library 6 的AOP實現


      最近 Enterprise Library 6 正式版發布了,距離上了版本又有一段時間.首先我們來看下面這張模塊圖,實線表示強依賴,虛線表示弱依賴(或可選的).
6.0版本全面支持.net Framework 4.5.

EntLib6

相對於前面5.0版本,移除了下面的模塊:

The Caching Application Block
The Cryptography Application Block
The Security Application Block

對於Cache可以考慮試用.net framework基類庫中的System.Runtime.Caching類,或是Windows Server AppFabric 緩存特性.

對於加密這一塊,可參考.NET Framework Cryptography Model來代替.

安全模塊可以采用Claims-based來代替,更加信息可參考MSDN.

參加兩個新的模塊:

    • Transient Fault Handling Application Block
    • Semantic Logging Application Block

變化:

這次有一項改動是那些模塊的功能類不再自動從Unity創建了,也就是引導也不依賴Unity容器組件. 這是區別5.0版本的,現在應該刪除下面代碼:

AddNewExtension<EnterpriseLibraryCoreExtension>


例如,使用Logging Application block模塊,那需要先使用靜態方法注冊一下:

                //From Entlib 6 document:Exception Handling Application Block objects can no longer be created 
                // automatically from the Unity DI container. 
                IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
                LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
                Logger.SetLogWriter(logWriterFactory.Create());


否則可能出現這樣的異常:

The LogWriter has not been set for the Logger static class. Set it invoking the Logger.SetLogWriter method.  


   基於6.0版本實現面向方向的編程AOP, 只需做少許修改即可.以前曾寫過一篇文章基於Enterprise Library 4.1版本. 首選,在Nuget上下載相關Enterprise Library 6模塊,參考下面的Nuget的XML文件:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="CommonServiceLocator" version="1.0" targetFramework="net45" />
  <package id="EnterpriseLibrary.Common" version="6.0.1304.0" targetFramework="net45" />
  <package id="EnterpriseLibrary.ExceptionHandling" version="6.0.1304.0" targetFramework="net45" />
  <package id="EnterpriseLibrary.ExceptionHandling.Logging" version="6.0.1304.0" targetFramework="net45" />
  <package id="EnterpriseLibrary.Logging" version="6.0.1304.0" targetFramework="net45" />
  <package id="EnterpriseLibrary.PolicyInjection" version="6.0.1304.0" targetFramework="net45" />
  <package id="EnterpriseLibrary.Validation" version="6.0.1304.0" targetFramework="net45" />
  <package id="Unity" version="3.0.1304.0" targetFramework="net45" />
  <package id="Unity.Interception" version="3.0.1304.0" targetFramework="net45" />
  <package id="xunit" version="1.9.1" targetFramework="net45" />
</packages>


用一個ServiceFactory來解析Interface,其靜態構造方法是這樣的,這只是這個類的片斷代碼:


        static ServiceFactory()
        {
            IUnityContainer container = new UnityContainer();
 
            string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "EntLib.Config");
            var map = new ExeConfigurationFileMap { ExeConfigFilename = path };
            var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
 
            try
            {
                var section = (UnityConfigurationSection)config.GetSection("unity");
                section.Configure(container, "DefContainer");
 
                //From Entlib 6 document:Exception Handling Application Block objects can no longer be created 
                // automatically from the Unity DI container. 
                IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
                LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
                Logger.SetLogWriter(logWriterFactory.Create());
 
                ExceptionPolicyFactory exceptionPolicyFactory = new ExceptionPolicyFactory(configurationSource);
                ExceptionPolicy.SetExceptionManager(exceptionPolicyFactory.CreateManager());
            }
            catch (InvalidOperationException ioe)
            {
                throw;
            }
 
            serviceLocator = new UnityServiceLocator(container);
        }

上面的代碼是從前面Assembly目錄,加載一個EntLib.Config的XML配置文件,讀取其中的Unity配置節與日志,異常處理的配置節.
下面以Demo個簡單的Interface, 我們在Method加上相應橫切的Attribute,分別用作 驗證,日志,異常處理:

    [ServiceContract]
    public interface IService1
    {
        [ValidationCallHandler]
        [LogCallHandler(BeforeMessage = "before GetData", AfterMessage = "after GetData",
           IncludeCallStack = true)]
        [ExceptionCallHandler("MyPolicy")]
        [OperationContract]
        string GetData([RangeValidator(1, RangeBoundaryType.Inclusive, 200, RangeBoundaryType.Inclusive)]
            int value);
 
        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
    }


最后我們用基於xunit的UnitTest來驗證一下, AOP攔截對方法參數的驗證,之前Method限制了參數值的范圍是1-200,第二個方法故意觸發這個邏輯.
 

        [Fact]
        public void GetDataWithCuttingConcern()
        {
            //Arrange
            var service = ServiceFactory.GetInstance<WcfService1.IService1>();
            //Act
            string result=service.GetData(100);
 
            //Assert
            Assert.NotNull(result);
        }
 
        [Fact]
        public void GetDataShouldAriseValidationException()
        {
            //Arrange and act
            var service = ServiceFactory.GetInstance<WcfService1.IService1>();
 
            //Assert
            Assert.Throws<ArgumentValidationException>(()=>service.GetData(300));
        }


鑒於篇幅有限,基於XML的Enterprise Library配置文件不在這兒就貼了,請參考以前的文章,使用時可用EntLib 6 配置控制台更新一下配置文件.


希望對您軟件開發有幫助.
你可能感興趣的文章:

使用Unity2.0的Interceptor實現簡單AOP
使用EnterpriseLibrary的PIAB與Unity搭建簡單AOP框架


作者:Petter Liu
出處:http://www.cnblogs.com/wintersun/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
該文章也同時發布在我的獨立博客中-Petter Liu Blog


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM