架(jia)構,改善程序復(fu)用(yong)性的設計~第五講 復(fu)用(yong)離不開反射和IOC
從(cong)本文標題中可以(yi)看出(chu),主(zhu)要(yao)說的(de)(de)是(shi)反(fan)射技(ji)術和控制反(fan)轉(IOC)技(ji)術,本文主(zhu)要(yao)先介(jie)紹一下我對這兩種(zhong)技(ji)術的(de)(de)理(li)解及它們的(de)(de)優缺(que)點,最后再用(yong)實例來說一下使用(yong)方法(fa)。
反(fan)射(she):可以使用反(fan)射(she)動態創(chuang)建(jian)類(lei)型的(de)(de)實(shi)(shi)例,將類(lei)型綁(bang)定(ding)到現(xian)有對象,或(huo)從現(xian)有對象獲取類(lei)型并調用其(qi)(qi)方法或(huo)訪(fang)問其(qi)(qi)字段和屬性。這里(li),它最重要的(de)(de)是“動態性”,即根據條(tiao)件動態創(chuang)建(jian)“指(zhi)定(ding)類(lei)型”的(de)(de)“實(shi)(shi)例”。
1 // Using GetType to obtain type information: 2 int i = 42; 3 System.Type type = i.GetType(); 4 System.Console.WriteLine(type);
結果是:
System.Int32
本示例使用靜態方法 GetType(Object 基類派生的所(suo)有類型都繼承該方法) 獲取(qu)變量類型的簡單反(fan)射(she)實例
1 // Using Reflection to get information from an Assembly: 2 System.Reflection.Assembly o = System.Reflection.Assembly.Load("mscorlib.dll"); 3 System.Console.WriteLine(o.GetName());
結果是:
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
本示例使用(yong)反射(she)獲取已加載的程序集的完整名稱(cheng)
反射一般用在以下情況中:
-
需要訪問程(cheng)序元數據的屬(shu)性。linq to sql 中(zhong)使用很多
-
執(zhi)行后期(qi)綁(bang)定,訪問在(zai)運行時創建(jian)的類(lei)型(xing)的方法。與工廠模(mo)式一起使用,根據配置文(wen)件(jian)中的類(lei)型(xing)來動態建(jian)立實例
IOC:(Inversion of Control,英(ying)文縮寫為IoC)是一個(ge)重要(yao)的面(mian)向對象編程的法則來削減計算機程序(xu)的耦合問(wen)題(ti)。 控制反轉還有一個(ge)名字(zi)叫做依(yi)賴(lai)注入(ru)(Dependency Injection)。簡稱DI。實現IOC的架(jia)構有很多(duo)如:Avalon 、Spring、JBoss及(ji)Unity等(deng)。
理(li)解IOC:可以把(ba)IoC模式看做是(shi)(shi)(shi)工廠模式的升華,可以把(ba)IoC看作是(shi)(shi)(shi)一(yi)個大(da)工廠,只不過這個大(da)工廠里要生成的對象都是(shi)(shi)(shi)在XML文件中(zhong)給出(chu)定義的,然(ran)后利用Java 的“反(fan)射”編程,根據XML中(zhong)給出(chu)的類名(ming)生成相應的對象。
實現非常簡(jian)單,根據容易名稱去創建對象即可
1 /// <summary> 2 /// The static factory of container 3 /// </summary> 4 public sealed class ContainerManager 5 { 6 /// <summary> 7 /// Creates the specified container instance . 8 /// </summary> 9 /// <param name="containerName">Name of the container.</param> 10 /// <returns></returns> 11 public static IContainerContext GetContainer(string containerName) 12 { 13 return new UnityContainerContext(containerName); 14 } 15 }
以(yi)下(xia)是在實(shi)際項目中的(de)使(shi)用(yong),IOC架(jia)構是用(yong)Unity,它的(de)基(ji)礎(chu)代(dai)碼(ma)是:
1 /// <summary> 2 /// The specific container context for Unity 3 /// </summary> 4 public class UnityContainerContext : ContainerContextBase 5 { 6 #region Fields 7 8 /// <summary> 9 /// The lock used for synchronous 10 /// </summary> 11 private static readonly object _synlock = new object(); 12 13 #endregion 14 15 #region Constructor 16 17 /// <summary> 18 /// Initializes a new instance of the <see cref="UnityContainerContext"/> class. 19 /// </summary> 20 /// <param name="name">The name.</param> 21 public UnityContainerContext(string name) 22 : base(name) 23 { 24 } 25 26 #endregion 27 28 #region Properties 29 30 /// <summary> 31 /// Gets the current context. 32 /// </summary> 33 /// <value>The current context.</value> 34 private HttpContext CurrentContext 35 { 36 get 37 { 38 HttpContext context = HttpContext.Current; 39 if (context == null) 40 { 41 throw new Exception("The current httpcontext is null"); 42 } 43 return context; 44 } 45 } 46 47 #endregion 48 49 #region Override Methods 50 51 /// <summary> 52 /// Initializes container. 53 /// </summary> 54 public override void Initialize() 55 { 56 OnBeforeInitialized(new ContainerEventArgs(this, ContainerType.Unity)); 57 58 if (CurrentContext.Application[Name] == null) 59 { 60 lock (_synlock) 61 { 62 if (CurrentContext.Application[Name] == null) 63 { 64 IUnityContainer currentContainer = new UnityContainer(); 65 UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection; 66 section.Containers[Name].Configure(currentContainer); 67 CurrentContext.Application[Name] = currentContainer; 68 } 69 } 70 } 71 72 OnAfterInitialized(new ContainerEventArgs(this, ContainerType.Unity)); 73 } 74 75 /// <summary> 76 /// Resolves this instance. 77 /// </summary> 78 /// <typeparam name="T">Parameter type.</typeparam> 79 /// <returns></returns> 80 public override T Resolve<T>() 81 { 82 try 83 { 84 Initialize(); 85 86 IUnityContainer currentContainer = CurrentContext.Application[Name] as IUnityContainer; 87 return currentContainer.Resolve<T>(); 88 } 89 catch(Exception ex) 90 { 91 OnResolveFailed(new ContainerFailedEventArgs(this, ContainerType.Unity, ex)); 92 return default(T); 93 } 94 } 95 96 /// <summary> 97 /// Tears down. 98 /// </summary> 99 public override void TearDown() 100 { 101 OnBeforeTearDown(new ContainerEventArgs(this, ContainerType.Unity)); 102 103 CurrentContext.Application[Name] = null; 104 105 OnAfterTearDown(new ContainerEventArgs(this, ContainerType.Unity)); 106 } 107 108 #endregion 109 110 }
在項目中(zhong)通過(guo)unity來創建對象的(de)代碼(ma)是:
1 /// <summary> 2 /// 數據層實體的個性操作(zuo)對(dui)象 3 /// </summary> 4 /// <typeparam name="TEntity"></typeparam> 5 /// <returns></returns> 6 protected TEntity LoadRepositoryEntity<TEntity>() 7 { 8 IContainerContext container = ContainerManager.GetContainer("repositoryContainer"); 9 return container.Resolve<TEntity>(); 10 }
這樣,在BLL層調(diao)用DAL層對(dui)象(xiang)時,可(ke)以通(tong)過LoadRepositoryEntity泛型方法來實現。