IoC之AutoFac(一)——簡單使用和組件註冊

閱讀目錄html

 


1、AutoFac簡單使用

複製代碼
 1 namespace AutofacDemo
 2 {
 3     class Program
 4     {
 5         //用於存儲容器的屬性
 6         private static IContainer Container { get; set; }
 7         static void Main(string[] args)
 8         {
 9             //獲取容器
10             var builder = new ContainerBuilder();
11             //註冊組件(類),並公開服務(接口)
12             builder.RegisterType<ConsoleOutput>().As<IOutput>();
13             builder.RegisterType<TodayWriter>().As<IDateWriter>();
14             //存儲容器
15             Container = builder.Build();
16 
17             WriteDate();//輸出當前的日期
18         }
19         public static void WriteDate()
20         {
21             using (var scope=Container.BeginLifetimeScope())
22             {
23                 //解析組件(功能相似於new一個IDateWriter的實現類)
24                 var writer = scope.Resolve<IDateWriter>();
25                 writer.WriteDate();
26             }
27         }
28     }
29     //輸出功能接口
30     public interface IOutput
31     {
32         void Write(string content);
33     }
34    //控制檯輸出類
35     public class ConsoleOutput : IOutput
36     {
37         public void Write(string content)
38         {
39             Console.WriteLine(content);
40         }
41     }
42     //輸出日期的接口
43     public interface IDateWriter
44     {
45         void WriteDate();
46     }
47    
48    //輸出今天日期的類
49     public class TodayWriter : IDateWriter
50     {
51         private IOutput _output;//輸出日期的類依賴IOutput
52         public TodayWriter(IOutput output)
53         {
54             this._output = output;
55         }
56         public void WriteDate()
57         {
58             this._output.Write(DateTime.Today.ToShortDateString());
59         }
60     }
61 }
複製代碼

應用程序執行過程:函數

  「WriteDate」方法向Autofac詢問IDateWriter。ui

  Autofac看到IDateWriter映射到TodayWriter,因此開始建立一個TodayWriter。this

  Autofac認爲TodayWriter在其構造函數中須要一個IOutput。spa

  Autofac看到IOutput映射到ConsoleOutput,因此建立一個新的ConsoleOutput實例。.net

  Autofac使用新的ConsoleOutput實例來完成TodayWriter的構建。code

  Autofac將「WriteDate」的徹底構建的TodayWriter返回給消費者。htm

  以後,若是您但願應用程序編寫不一樣的日期,則能夠實現不一樣的IDateWriter,而後在應用程序啓動時更改註冊。你沒必要改變任何其餘類。 這樣就實現了反轉控制!對象


 

2、註冊

      使用Autofac 註冊組件的任務是:經過建立一個ContainerBuilder而且告知builder 哪些組件公開哪些服務。blog

2.1 註冊方式

複製代碼
 1  // 建立組件/服務註冊的容器
 2             var builder = new ContainerBuilder();
 3 
 5             ////----------------------1、反射組件----------------////
 6             // 反射組件方法1---經過類型註冊
 7             builder.RegisterType<ConsoleOutput>().As<IOutput>();
 8             // 反射組件方法2---經過構造函數註冊
 9             builder.RegisterType<TodayWriter>()
10                    .UsingConstructor(typeof(IOutput)).As<IDateWriter>();
11             
12      
13 
14             ////--------------------2、實例組件----------------------////
15             // 註冊建立的對象實例,把該實例做爲一個服務
16             var output = new ConsoleOutput();
17             builder.RegisterInstance(output).As<IOutput>();
18             //不影響系統中原有的單例
19             builder.RegisterInstance(MySingleton.GetInstance()).ExternallyOwned();  
20 
21             
22 
23             ////------------------3、Lambda表達式組件---------------////
24             //參數c是組件上下文(一個IComponentContext對象) ,此處該組件被建立。您可使用它來解析來自於容器的其餘組件,從而幫助你建立組件。
25 
26             builder.Register(c => new TodayWriter(c.Resolve<IOutput>())).As<IDateWriter>();
27 
28             //分離組件建立最大的好處就是具體類型能夠變化
29             //一個組件分離的Demo:註冊一個信用卡組件
30             builder.Register<CreditCard>(
31                 (c, p) =>
32                 {
33                     var accountId = p.Named<string>("accountId");
34                     if (accountId.StartsWith("9"))
35                     {
36                         return new GoldCard(accountId);
37                     }
38                     else
39                     {
40                         return new StandardCard(accountId);
41                     }
42                 });
43             //根據參數不一樣獲取不一樣種類的信用卡類實例
44             var card = container.Resolve<CreditCard>(new NamedParameter("accountId", "12345"));
45 
46 
47             ////-------------------------4、泛型註冊------------------////
48             //泛型註冊,能夠經過容器返回List<T> 如:List<string>,List<int>等等
49             builder.RegisterGeneric(typeof(List<>)).As(typeof(IList<>)).InstancePerLifetimeScope();
50             using (IContainer container = builder.Build())
51             {
52                 IList<string> ListString = container.Resolve<IList<string>>();
53             }
54 
55 
56             ////-----------------------5、服務與組件-------------------////
57             builder.RegisterType<ConsoleLogger>();//默認把註冊類型做爲公開服務
58             builder.RegisterType<ConsoleLogger>().As<ILogger>().As<IMyLogger>();//能夠公開任意多個服務,可是默認的註冊類型會被覆蓋
59             builder.RegisterType<ConsoleLogger>().AsSelf().As<ILogger>();//加上AsSelf()默認的註冊類型不會被覆蓋
60             //當公開的服務重名時,服務使用的默認組件是後註冊的那個
61             builder.Register<ConsoleLogger>().As<ILogger>();
62             builder.Register<FileLogger>().As<ILogger>();//默認使用後註冊的FileLogger
63             //阻止該默認行爲,使用builder.Register<FileLogger>().As<ILogger>().PreserveExistingDefaults(),這樣不會覆蓋之前註冊的組件
64 
65 
66             ////-----------6、條件註冊(IfNotRegistered,OnlyIf)-------////
67             //HandlerC不會被註冊
68             builder.RegisterType<HandlerA>()
69                     .AsSelf()
70                     .As<IHandler>()
71                     .IfNotRegistered(typeof(HandlerB));
72             builder.RegisterType<HandlerB>()
73                    .AsSelf()
74                    .As<IHandler>();
75             builder.RegisterType<HandlerC>()
76                    .AsSelf()
77                    .As<IHandler>()
78                    .IfNotRegistered(typeof(HandlerB));
79 
80             //只有IService和HandlerB都註冊時,纔會去註冊Manager
81             builder.RegisterType<Manager>()
82                    .As<IManager>()
83                    .OnlyIf(reg =>
84                      reg.IsRegistered(new TypedService(typeof(IService))) &&
85                      reg.IsRegistered(new TypedService(typeof(HandlerB))));
86 
87 
88             // 編譯容器完成註冊且準備對象解析
89              Container = builder.Build();
90 
91             // 如今你可使用 Autofac 解析服務. 例如,這行將執行註冊的lambda表達式對於 IConfigReader 服務.
92              using (var scope = Container.BeginLifetimeScope())
93              {
94                  var writer = Container.Resolve<IOutput>();
95                  var dataWriter = Container.Resolve<IDateWriter>();
96                  writer.Write("111");//輸出111
97                  dataWriter.WriteDate();//輸出當前日期
98                  Console.ReadKey();
99              }
複製代碼

 

2.2 帶參數註冊

一、參數類型

  Autofac支持的參數類型有三種:

    NamedParameter - 經過名稱匹配目標參數

    TypedParameter - 經過類型匹配目標參數(須要精確匹配類型)

    ResolvedParameter - 靈活的參數匹配

  例子:一個讀取配置文件的類,構造器須要傳入參數:節點名稱

複製代碼
1 public class ConfigReader : IConfigReader
2     {
3         public ConfigReader(string configSectionName)
4         {
5             // 存儲配置的節點名稱
6         }
7 
8         // ...讀取基於節點名稱的配置
9     }
複製代碼

二、反射組件參數

Parameters with Reflection Components----註冊時傳入

複製代碼
 1 // 使用一個命名參數:
 2 builder.RegisterType<ConfigReader>()
 3        .As<IConfigReader>()
 4        .WithParameter("configSectionName", "mySectionName");
 5 
 6 // 使用一個類型參數:
 7 builder.RegisterType<ConfigReader>()
 8        .As<IConfigReader>()
 9        .WithParameter(new TypedParameter(typeof(string), "mySectionName"));
10 
11 // 使用一個解析參數:
12 builder.RegisterType<ConfigReader>()
13        .As<IConfigReader>()
14        .WithParameter(
15          new ResolvedParameter(
16            (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "configSectionName",
17            (pi, ctx) => "mySectionName"));
複製代碼

三、Lambda表達式組件參數

Parameters with Lambda Expression Components----解析時傳入

  在組件註冊表達式中,你能夠經過改變委託簽名使用傳入參數進行註冊,代替僅僅接收一個IComponentContext參數,一個IComponentContext 和 IEnumerable<Parameter>參數:
1 builder.Register((c, p) =>
2                  new ConfigReader(p.Named<string>("configSectionName")))
3        .As<IConfigReader>();

 當你解析參數時,你的lambda將使用這些參數來傳入值:

 var reader = scope.Resolve<IConfigReader>(new NamedParameter("configSectionName", "mySectionName"));

 

 參考文章:

  一、https://blog.csdn.net/chiyueqi/article/details/52446569

  二、http://www.yuanjiaocheng.net/Autofac/register-parameters.html

相關文章
相關標籤/搜索