Lind.DDD.IoC依賴註入與面向方面的實現

来源:http://www.cnblogs.com/lori/archive/2016/02/01/5175786.html
-Advertisement-
Play Games

回到目錄 IoC是解耦的靈魂,很難想像一個框架中沒有IoC會變成什麼樣子,Lind.DDD里的IoC是通過Unity實現的,由依賴註入(unity)和方法攔截組成(Interception),依賴註入可以通過事前定義好的實現方式去動態建立某個介面的實例,例如,在倉儲介面IRepository里,你可


回到目錄

IoC是解耦的靈魂,很難想像一個框架中沒有IoC會變成什麼樣子,Lind.DDD里的IoC是通過Unity實現的,由依賴註入(unity)和方法攔截組成(Interception),依賴註入可以通過事前定義好的實現方式去動態建立某個介面的實例,例如,在倉儲介面IRepository里,你可以在配置文件中定義它由EF實現,也可以讓它由Mongodb實現,而表現出來的結果就是數據的持久化方式的不同。

模塊的結構

服務定位器ServiceLocator

服務定位器可以幫助我們在不引用程式集的情況下,自動將它進行反射,這對於某些擴展註入的場合,非常有用,也是通過單例模式實現的。

    /// <summary>
    /// Represents the Service Locator.
    /// </summary>
    public sealed class ServiceLocator : IServiceProvider
    {
        #region Private Fields
        private readonly IUnityContainer _container;
        #endregion

        #region Private Static Fields
        private static readonly ServiceLocator instance = new ServiceLocator();
        #endregion

        #region Ctor
        /// <summary>
        /// Initializes a new instance of ServiceLocator class.
        /// </summary>
        private ServiceLocator()
        {
            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

            if (section == null)
            {
                var unityConfig = System.AppDomain.CurrentDomain.BaseDirectory + @"\IoC.config";
                var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = unityConfig };
                var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                section = (UnityConfigurationSection)configuration.GetSection("unity");
            }

            if (section == null)
                throw new ArgumentException("請配置unity節點...");

            _container = new UnityContainer();

            #region 裝載config中的類型
            section.Configure(_container);
            #endregion

            #region 註冊動態類型
            LoadDynamicType(_container);
            #endregion

        }
        #endregion

        #region Public Static Properties
        /// <summary>
        /// Gets the singleton instance of the ServiceLocator class.
        /// </summary>
        public static ServiceLocator Instance
        {
            get { return instance; }
        }

        #endregion

        #region Private Methods
        /// <summary>
        /// 裝載一批動態的類型
        /// Author:zhangzhanling
        /// Date:2015-04-03
        /// </summary>
        private void LoadDynamicType(IUnityContainer _container)
        {
            //unity動態類型註入,各個程式集用,分開,支持*通配符號
            string unityDynamicAssembly = System.Configuration.ConfigurationManager.AppSettings["unityDynamicAssembly"];
            //是否同時啟動數據集緩存策略
            string unityCachingDoing = System.Configuration.ConfigurationManager.AppSettings["unityCachingDoing"] ;
            InjectionMember[] injectionMembers = new InjectionMember[] { };
            if (unityCachingDoing == "1")
            {
                injectionMembers = new InjectionMember[] { new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<CachingBehavior>() };
            }
            if (!string.IsNullOrWhiteSpace(unityDynamicAssembly))
            {
                Array.ForEach(unityDynamicAssembly.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries), dllName =>
                {
                    var baseDir = AppDomain.CurrentDomain.BaseDirectory;
                    if (System.Web.HttpContext.Current != null)
                    {
                        baseDir += "bin";
                    }
                    var files = Directory.GetFiles(baseDir, dllName);
                    var iTypes = new List<Type>();
                    foreach (var file in files)
                    {
                        var interfaceASM = Assembly.LoadFrom(Path.Combine(baseDir, file));
                        var types = from t in interfaceASM.GetTypes()
                                    where !string.IsNullOrWhiteSpace(t.Namespace)
                                    select t;

                        foreach (var type in types)
                        {
                            if (type.GetInterfaces() != null && type.GetInterfaces().Any())
                                foreach (var father in type.GetInterfaces())
                                {
                                    _container.RegisterType(father
                                        , type
                                        , injectionMembers);
                                }
                        }
                    }
                });

            }

        }

        private IEnumerable<ParameterOverride> GetParameterOverrides(object overridedArguments)
        {
            List<ParameterOverride> overrides = new List<ParameterOverride>();

            Type argumentsType = overridedArguments.GetType();
            argumentsType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .ToList()
                .ForEach(property =>
                {
                    var propertyValue = property.GetValue(overridedArguments, null);
                    var propertyName = property.Name;
                    overrides.Add(new ParameterOverride(propertyName, propertyValue));
                });

            return overrides;
        }
        #endregion

        #region Public Methods

        /// <summary>
        /// Gets the service instance with the given type.
        /// </summary>
        /// <typeparam name="T">The type of the service.</typeparam>
        /// <returns>The service instance.</returns>
        public T GetService<T>()
        {
            return _container.Resolve<T>();
        }
        /// <summary>
        /// Gets the service instance with the given type by using the overrided arguments.
        /// </summary>
        /// <typeparam name="T">The type of the service.</typeparam>
        /// <param name="overridedArguments">The overrided arguments.</param>
        /// <returns>The service instance.</returns>
        public T GetService<T>(object overridedArguments)
        {
            var overrides = GetParameterOverrides(overridedArguments);
            return _container.Resolve<T>(overrides.ToArray());
        }
        /// <summary>
        /// Gets the service instance with the given type by using the overrided arguments.
        /// </summary>
        /// <param name="serviceType">The type of the service.</param>
        /// <param name="overridedArguments">The overrided arguments.</param>
        /// <returns>The service instance.</returns>
        public object GetService(Type serviceType, object overridedArguments)
        {
            var overrides = GetParameterOverrides(overridedArguments);
            return _container.Resolve(serviceType, overrides.ToArray());
        }
        #endregion

        #region IServiceProvider Members
        /// <summary>
        /// Gets the service instance with the given type.
        /// </summary>
        /// <param name="serviceType">The type of the service.</param>
        /// <returns>The service instance.</returns>
        public object GetService(Type serviceType)
        {
            return _container.Resolve(serviceType);
        }

        #endregion
    }

Interception方法攔截

這是AOP面向方面編程里的一個概念,它在方法進行前或者後,對它進行攔截,並註入新的業務邏輯,這種方法一般是介面方法和虛方法,為了方便大家使用,大家抽象了一個基類

    /// <summary>
    /// 攔截器抽象基類
    /// 實現攔截器的項目需要繼承此類,只引用Microsoft.Practices.Unity.Interception.dll程式集
    /// </summary>
    public abstract class InterceptionBase : IInterceptionBehavior
    {
        /// <summary>
        /// 獲取當前行為需要攔截的對象類型介面。
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        /// <summary>
        ///通過實現此方法來攔截調用並執行所需的攔截行為。
        /// </summary>
        /// <param name="input">調用攔截目標時的輸入信息</param>
        /// <param name="getNext">通過行為鏈來獲取下一個攔截行為的委托</param>
        /// <returns>從攔截目標獲得的返回信息</returns>
        public abstract IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext);

        /// <summary>
        /// 獲取一個<see cref="Boolean"/>值,該值表示當前攔截行為被調用時,是否真的需要執行攔截動作
        /// </summary>
        public bool WillExecute
        {
            get { return true; }
        }
    }

下麵是一個異常攔截器的實現

 /// <summary>
    /// 攔截器實例,具體攔截器可以自己去建立項目來實現,需要實現IInterceptionBehavior介面
    /// 表示用於異常日誌記錄的攔截行為。
    /// </summary>
    public class ExceptionLoggingBehavior : InterceptionBase
    {

        /// <summary>
        /// 通過實現此方法來攔截調用並執行所需的攔截行為。
        /// </summary>
        /// <param name="input">調用攔截目標時的輸入信息。</param>
        /// <param name="getNext">通過行為鏈來獲取下一個攔截行為的委托。</param>
        /// <returns>從攔截目標獲得的返回信息。</returns>
        public override IMethodReturn Invoke(
            IMethodInvocation input,
            GetNextInterceptionBehaviorDelegate getNext)
        {
            //方法執行前
            var methodReturn = getNext().Invoke(input, getNext);//原方法被執行
            //方法執行後
            if (methodReturn.Exception != null)
            {
                Console.WriteLine(methodReturn.Exception.Message);
                Logger.LoggerFactory.Instance.Logger_Error(methodReturn.Exception);
            }
            return methodReturn;
        }

    }

下麵是IOC所需要的配置

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <!--BEGIN: Unity-->
  <unity>
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
    <container>
      <extension type="Interception" />
      <!--被攔截的類型-->
      <register type="Lind.DDD.Test.AOP,Lind.DDD.Test"  mapTo="Lind.DDD.Test.AOP,Lind.DDD.Test">
        <interceptor type="VirtualMethodInterceptor"/>
        <!--InterfaceInterceptor,VirtualMethodInterceptor,TransparentProxyInterceptor,這種方法要求被攔截的類繼承MarshalByRefObject-->
        <interceptionBehavior  type="Lind.DDD.IoC.Interception.ExceptionLoggingBehavior,Lind.DDD" />
        <!--攔截行為-->
      </register>
    </container>
  </unity>

</configuration>
View Code

非常感謝各位的閱讀!

回到目錄

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <!-- MyBatis框架 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> <!-- MySql資料庫驅動
  • 之前寫了一題費用流,竟然硬是在寫SPFA時為DIS數組賦初始值用了MEMSET數組QAQ 調試了很久也沒有弄明白自己是卡在那裡了,,,感覺被自己蠢哭了QWQ 錯誤的姿勢!! #include <cstring> #include <iostream> #include <cstdio> using
  • list是一種有序的集合,可以隨時添加和刪除其中的元素。定義有序的集合: classmates = ['Michael', 'Bob', 'Tracy'] 用len()函數可以獲得list元素的個數: len(classmates) 用索引來訪問list中每一個位置的元素,記得索引是從0開始的: c...
  • >>> print('The quick brown fox', 'jumps over', 'the lazy dog') The quick brown fox jumps over the lazy dog print()會依次列印每個字元串,遇到逗號“,”會輸出一個空格,因此,輸出的字元串是...
  • 試題描述: 有 n 個同學(編號為 1 到 n )正在玩一個信息傳遞的游戲。在游戲里每人都有一個固定的信息傳遞對象,其中,編號為 i 的同學的信息傳遞對象是編號為 T_i 的同學。游戲開始時,每人都只知道自己的生日。之後每一輪中,所有人會同時將自己當前所知的生日信息告訴各自的信息傳遞對象(註意:可能
  • 回到目錄 分頁組件網上有很多,MVC.Pager,JSPager等,通過實現方式大體分為前端分頁和後端分頁,前端分頁是前臺對list記憶體本地集合進行分頁,缺點就是在大數據情況下,記憶體占用過高;後端分頁就是UI把要返回的頁號告訴後臺,由後臺組織數據並返回,這種方法就是我們經常看到的了;而根據後臺集合種
  • 俗話說,自己寫的代碼,6個月後也是別人的代碼……複習!複習!複習!總結的知識點如下: 享元模式概念和實現例子 使用了享元模式的Java API String類 java.lang.Integer 的 valueOf(int)方法源碼分析 使用享元模式的條件 享元模式和單例模式的區別 前面的策略模式的
  • 序言 Nginx是lgor Sysoev為俄羅斯訪問量第二的rambler.ru站點設計開發的。從2004年發佈至今,憑藉開源的力量,已經接近成熟與完善。 Nginx功能豐富,可作為HTTP伺服器,也可作為反向代理伺服器,郵件伺服器。支持FastCGI、SSL、Virtual Host、URL Re
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...