架構,改善程序復用性的設計~第五講 復用離不開反射和IOC


從本文標題中可以看出,主要說的是反射技術和控制反轉(IOC)技術,本文主要先介紹一下我對這兩種技術的理解及它們的優缺點,最后再用實例來說一下使用方法。

反射:可以使用反射動態創建類型的實例,將類型綁定到現有對象,或從現有對象獲取類型並調用其方法或訪問其字段和屬性。這里,它最重要的是“動態性”,即根據條件動態創建“指定類型”的“實例”。

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 基類派生的所有類型都繼承該方法) 獲取變量類型的簡單反射實例

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

本示例使用反射獲取已加載的程序集的完整名稱

反射一般用在以下情況中:

  • 需要訪問程序元數據的屬性。linq to sql 中使用很多

  • 執行后期綁定,訪問在運行時創建的類型的方法。與工廠模式一起使用,根據配置文件中的類型來動態建立實例

IOC:(Inversion of Control,英文縮寫為IoC)是一個重要的面向對象編程的法則來削減計算機程序的耦合問題。 控制反轉還有一個名字叫做依賴注入(Dependency Injection)。簡稱DI。實現IOC的架構有很多如:Avalon 、Spring、JBoss及Unity等。

理解IOC:可以把IoC模式看做是工廠模式的升華,可以把IoC看作是一個大工廠,只不過這個大工廠里要生成的對象都是在XML文件中給出定義的,然后利用Java 的“反射”編程,根據XML中給出的類名生成相應的對象。

實現非常簡單,根據容易名稱去創建對象即可

 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     }

以下是在實際項目中的使用,IOC架構是用Unity,它的基礎代碼是:

  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     }

在項目中通過unity來創建對象的代碼是:

 1         /// <summary>
 2         /// 數據層實體的個性操作對象
 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層調用DAL層對象時,可以通過LoadRepositoryEntity泛型方法來實現。

 


免責聲明!

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



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