1. 程式人生 > >用Rider寫一個有IOC容器Autofac的.net core的程式

用Rider寫一個有IOC容器Autofac的.net core的程式

一:Autofac是一個和Java裡的Spring IOC容器一樣的東西,不過它確實沒有Spring裡的那麼方便,主要是在於它沒有提供足夠的Api和掃描方式等等,不過優點是它比Spring要快很多,而且Spring裡的通過註解注入、自動裝配、Aop等等通過自己寫一定的程式碼也是可以實現的;

二:這裡只先做一個最簡單的Autofac的演示,我這裡用的是Jetbrains的Rider,說實在話如果VS和Rider在沒有配置的前提下個人還是覺得Rider好用,特別是一些快捷輸入和原始碼檢視比VS好用的多;

2.1.開啟Rider,然後新建一個空的解決方案叫AutofacSolution1;

2.2.然後在此之上Add一個Project,選擇.Net Core區域裡的Console Application,如叫ConsoleApp1【注意C#實際程式設計裡主入口的Project儘量精簡,好能更好的設計出靈活的熱部署應用】。

2.3.通過Tools裡的Nuget安裝Autofac到這個Project裡來,然後在Dependency裡(VS裡對應的是References)的Packages裡就是我們通過Nuget安裝的依賴;

接下來就直接上程式碼了,一些用法和解釋也直接在程式碼裡:

class Program
    {
        
        public string Name { get; set; }
        
        static void Main(string[] args)
        {
            // builder一般只是用來註冊Bean的描述資訊的(轉java蠻久了,習慣了用bean稱呼一些特定領域的物件),
            var builder = new ContainerBuilder();
            // 注意,這裡是註冊了一個物件【也可以只註冊型別builder.RegisterType()】,然後還同時給這個物件進行一個熟悉的裝配,這裡要注意Resolve如果找不到bean是會報錯的
            // 如果不確定一定有可以用TryResolve,後面的AsSelf()表示將這個bean的型別以自己的型別為準,還可以通過.AsImplementedInterfaces()來表示Resolve時可以通過其介面來Resolve到bean
            // 後面還可以用.PropertiesAutowired()表示對Program類的這個bean做一個所有public set屬性的自動裝配,不過我們這裡手動去做了部分的自動裝配就不加這個了;
            // 這裡還可以設定生命週期,比如某個bean是單例的還是原型的還是基於執行緒的,還可以register一個Module還實現bean的分開註冊(Module物件不會註冊,它只起一個橋樑作用)
            builder.Register(c => new Program(){Name = c.Resolve<string>()}).AsSelf();
           
            // 還可以給builder新增監聽器,比如可以監聽IComponentRegistration配置完成的時候產生的事件,從而可以自定義的對它們做一些調整,類似Spring裡的BeanPostProcessor之類的
            builder.RegisterInstance("資料裡防靜電").Keyed<string>("a-str").AsSelf();
            
            // 注意一個builder物件不能同時Build()兩次
            // Build()返回IContainer物件,用於通過特定演算法獲取註冊的bean;
            var contailer = builder.Build();

            // 如果Program注入了兩個bean這裡只會取出最後注入的那個
            var program = contailer.Resolve<Program>();
            // 輸出了資料裡防靜電,說明兩個bean都注入成功,且完成的Program屬性的裝配;
            Console.WriteLine(program.Name);
            // 還可以通過這種方式獲取注入的某種型別的所有的bean;
            var programs = contailer.Resolve<IList<Program>>();
            Console.WriteLine(programs.Count);
            Console.WriteLine("Hello World!");
            
            var listStrType = typeof(List<>).MakeGenericType(typeof(string));
            var listStrInstance = Activator.CreateInstance(listStrType);
            listStrType.GetMethod("Add").Invoke(listStrInstance, new object[]{"u"});

            /**
             * 這裡給大家提供一下Spring裡的@Resource和@Primary以及@Component的實現方式:
             * 
[email protected]
其實是最簡單的,就是通過builder.RegisterType(type);來實現, * 先是通過AppDomain.CurrentDomain.GetAssemblies().Where(a => a.GetCustomAttributes()...)找出那些有[Component]特性的類,然後將他們註冊到Autofac裡; * * [email protected]就是在1的基礎上通過builder.Register(c => new Program(){Name = c.Resolve<string>()})和反射先建立Program物件, * 然後來對每個要注入的類判斷其所有的屬性找出那些有[Resource]的還是通過反射來注入屬性; * *
[email protected]
它是和@Component一樣是註解在需要生產bean的類上面,這個實現其實就是在2的基礎上c.Resolve(type)時的這個type是通過typeof(IList<>)的 * MakeGenericType(有@Resource的屬性的Type型別),然後就可以將所有的和屬性同類型的(Spring裡是有byType和byName的說法,這裡假設就是byType)bean都找出來 * 然後如果list裡只有一個則直接裝配,如果多個則找出有@Primary的那個bean(這幾個bean有共同的介面),如果都沒有則可以像Spring一樣丟擲異常; */ } }