Lind.DDD.IoC依賴注入與面向方(fang)面的實現
IoC是解(jie)耦的(de)(de)靈魂,很(hen)難想像一(yi)個框架中(zhong)(zhong)沒有IoC會變(bian)成什么樣子,Lind.DDD里的(de)(de)IoC是通過(guo)Unity實現(xian)(xian)的(de)(de),由(you)依(yi)賴(lai)注入(unity)和方(fang)法攔截組成(Interception),依(yi)賴(lai)注入可(ke)以通過(guo)事(shi)前定義好的(de)(de)實現(xian)(xian)方(fang)式(shi)去動(dong)態建立某(mou)個接口的(de)(de)實例,例如,在(zai)倉(cang)儲接口IRepository里,你可(ke)以在(zai)配置文件中(zhong)(zhong)定義它(ta)由(you)EF實現(xian)(xian),也可(ke)以讓(rang)它(ta)由(you)Mongodb實現(xian)(xian),而表現(xian)(xian)出來的(de)(de)結(jie)果就是數(shu)據的(de)(de)持久化方(fang)式(shi)的(de)(de)不同。
模塊的結構
服務定位器ServiceLocator
服務定(ding)位器可(ke)以幫助我們在不引用(yong)(yong)程序集的情況下,自動將它進行反射,這對于某(mou)些(xie)擴展注入的場合,非常有用(yong)(yong),也是通過單例模式實現的。
/// <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> /// 裝載一批動態(tai)的(de)類(lei)型 /// Author:zhangzhanling /// Date:2015-04-03 /// </summary> private void LoadDynamicType(IUnityContainer _container) { //unity動態類型注入(ru),各個(ge)程(cheng)序集用,分開,支持*通(tong)配符號 string unityDynamicAssembly = System.Configuration.ConfigurationManager.AppSettings["unityDynamicAssembly"]; //是(shi)否同時啟動數據集緩存策略 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方法攔截
這(zhe)是AOP面向方(fang)(fang)面編程里的一(yi)個(ge)概念,它在方(fang)(fang)法(fa)進(jin)行前或者后,對它進(jin)行攔截(jie),并注入新的業務邏輯,這(zhe)種方(fang)(fang)法(fa)一(yi)般是接口方(fang)(fang)法(fa)和虛方(fang)(fang)法(fa),為了方(fang)(fang)便大家(jia)使用,大家(jia)抽象了一(yi)個(ge)基類
/// <summary> /// 攔截器(qi)抽象基類 /// 實現攔截器的項(xiang)目需(xu)要繼承(cheng)此類,只引(yin)用Microsoft.Practices.Unity.Interception.dll程序集 /// </summary> public abstract class InterceptionBase : IInterceptionBehavior { /// <summary> /// 獲取當前行為(wei)需要攔截的對象(xiang)類型接(jie)口。 /// </summary> /// <returns></returns> public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } /// <summary> ///通(tong)過(guo)實現此方法來攔截調用并執行(xing)所需的(de)攔截行(xing)為。 /// </summary> /// <param name="input">調用(yong)攔截目(mu)標時的輸入信(xin)息</param> /// <param name="getNext">通過行為鏈來(lai)獲取(qu)下(xia)一(yi)個攔截(jie)行為的委托</param> /// <returns>從攔截目標獲得的返回(hui)信息</returns> public abstract IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext); /// <summary> /// 獲取一個<see cref="Boolean"/>值,該值表示(shi)當前攔截行為(wei)被(bei)調用時,是否真(zhen)的(de)需要執行攔截動作 /// </summary> public bool WillExecute { get { return true; } } }
下(xia)面是一個異常攔(lan)截器的實現
/// <summary> /// 攔截器(qi)實(shi)例(li),具(ju)體攔截器(qi)可以(yi)自己去(qu)建立(li)項目來實(shi)現(xian),需要實(shi)現(xian)IInterceptionBehavior接口 /// 表(biao)示用于異常(chang)日志記錄的攔截行為。 /// </summary> public class ExceptionLoggingBehavior : InterceptionBase { /// <summary> /// 通(tong)過實(shi)現此方法來攔(lan)截(jie)調用并執行(xing)所需的攔(lan)截(jie)行(xing)為。 /// </summary> /// <param name="input">調用攔截目標(biao)時的(de)輸入信息。</param> /// <param name="getNext">通過行(xing)為鏈來(lai)獲取下一個攔截行(xing)為的委托。</param> /// <returns>從攔截目標獲得的返回信(xin)息。</returns> public override IMethodReturn Invoke( IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { //方法執行前 var methodReturn = getNext().Invoke(input, getNext);//原方法被執行 //方(fang)法執行后 if (methodReturn.Exception != null) { Console.WriteLine(methodReturn.Exception.Message); Logger.LoggerFactory.Instance.Logger_Error(methodReturn.Exception); } return methodReturn; } }
下面是IOC所需(xu)要的配(pei)置
<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>
非常感(gan)謝(xie)各位(wei)的閱讀!