回到目錄 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
非常感謝各位的閱讀!