上篇文章中,舉了一個Autofac的簡單例子,園友eflay反應:
“雖然對autofac架構原理還是完全不懂,不過基本是明白ioc的用途了,會從已注冊的類中找出符合接口的類來調用構造函數進行構造”
所以這篇文章,還是針對上次的例子,不引用Autofac,完全使用自己寫的FakeAutofac, 也讓Demo運行起來.
由於本篇文章和以前文章關聯度很高,源代碼也是從以前的演化過來的。沒有看過以前文章的園友,麻煩移步這里, 下載第二篇的源代碼,思考一下如何實現例子中Autofac使用到的功能。
IoC容器Autofac(1) -- 什么是IoC以及理解為什么要使用Ioc
IoC容器Autofac(2) - 一個簡單示例(附demo源碼)
這里是本文相關的源代碼 AutofacDem0(1).zip, 源代碼主要涉及的知識有反射,泛型,委托。
這篇文章本人沒有把握能夠把所有的東西都講的非常淺顯易懂, 不過好在有源代碼, 代碼量不大,加有很多注釋,大家可以對比理解一下。
如果對源代碼有任何建議和問題,可以留言或者寫在評論里,我盡量回復和解答。
閱讀目錄:
一. 開始前的分析
二. 實現過程中遇到的一些難點
三. 總結
一、開始前的分析
我們主要使用到了Autofac中的類和方法:
類ContainerBuilder中的方法:
RegisterType<T>()//注冊類型T AsImplementedInterfaces()//表示注冊的類型,以接口的方式注冊 Build()//創建一個容器
接口IContainer的方法:
Resolve<T>()//從容器中取出一個T類型的實例
這里是類圖:
二、實現過程中遇到的一些難點
注冊類型可以使用集合類來保存,當需要某種類型的實例的時候,可以使用反射調用構造函數直接構造該類型的實例。
這樣看起來還蠻簡單的,但是還有一些難點, 大家在看源代碼的過程中,可以帶着這些問題看看是如何解決這些問題的。
1. 如何實現AsImplementedInterfaces()方法?
這個方法的作用是,指定注冊類型以接口形式存在, 比如,
當我運行了下面代碼后
builder.RegisterType<ListMovieFinder>().AsImplementedInterfaces(); //以類ListMovieFinder的接口IMovieFinder注冊
那么我使用 Resolve<IMovieFinder>()要獲取一個接口實例的時候,會返回一個ListMovieFinder的實例
2. 如何實現對同一個類型的注冊,后面的覆蓋前面的注冊, 如源代碼中:
builder.RegisterType<ListMovieFinder>().AsImplementedInterfaces();
builder.RegisterType<DBMovieFinder>().AsImplementedInterfaces();
后面的DBMovieFinder會覆蓋掉ListMovieFinder的注冊
這樣,當我調用 Resolve<IMovieFinder>()要獲取一個接口實例的時候,會返回一個DBMovieFinder的實例
3.當用反射調用構造函數的時候,如果構造函數中有參數,這些參數也由Autofac構造。
比如,當我們Resolve<MPGMovieLister>()想獲取MPGMovieLister實例的時候, MPGMovieLister的構造函數需要一個IMovieFinder類型的參數,如何這個參數也由Autofac創建?
三、總結
源代碼只是模仿Autofac的一部分功能,只能算是Autofac現有功能中的九牛一毛了。
直接使用別人寫好的框架,自然是最簡單不過的。 但是通過自己動手寫源代碼模仿Autofac的實現,自己學到更多,同時寫非常感謝那些做開源框架和產品的開發者。
感謝園友eflay, 因為這個,我才有了這個想法,期間幾次想放棄寫這篇文章,但是"知其然還要知其所以然"的想法又讓我堅持了下去。
希望源代碼和文章能夠對大家有所幫助。
本文相關源代碼: AutofacDem0(1).zip
相關文章:
IoC容器Autofac(2) - 一個簡單示例(附demo源碼)