IoC之AutoFac(二)——解析服務
1、Resolve方法
在您的組件註冊了適當的服務後,您可以從內置的容器和子生命周期範圍中解析服務。 您可以使用Resolve()方法,還是使用上篇的例子:
1 private static IContainer Container { get; set; } 2 static void Main(string[] args) 3 { 4 var builder = new ContainerBuilder(); 5 //註冊服務 6 builder.RegisterType<ConsoleOutput>().As<IOutput>();7 Container = builder.Build(); 8 //解析服務 9 using (var scope=Container.BeginLifetimeScope()) 10 { 11 var output= scope.Resolve<IOutput>(); 12 output.Write("outputsomething"); 13 Console.ReadKey(); 14 }15 }
解析服務時,Autofac將自動鏈接服務的整個依賴關系層次,並解析完全構建服務所需的任何依賴關系。 如果您的循環依賴關系被錯誤地處理,或者缺少必需的依賴關系,那麽您將得到一個DependencyResolutionException。
2、TryResolve和ResolveOptional方法
如果您有可能註冊或可能不被註冊的服務,您可以使用ResolveOptional()或TryResolve()來嘗試對服務進行有條件解決:
1 //解析服務 2 using (var scope = Container.BeginLifetimeScope())3 { 4 //1.ResolveOptional:IOutput註冊的話解析,未被註冊返回null 5 var service = scope.ResolveOptional<IOutput>(); 6 7 //2.TryResolve:IOutput註冊的話解析獲取一個類型實例,未註冊返回null 8 IOutput output = null; 9 //如果有IOutPut服務,執行輸出 10 if (scope.TryResolve<IOutput>(out output)) 11 { 12 output.Write("outputsomething"); 13 } 14 Console.ReadKey(); 15 }
3、解析服務時傳參
解析服務的時候,您可能會發現需要將參數傳遞給Autofac。 (如果您在註冊時知道值,則可以在註冊中提供它們,詳細見上篇。)Resolve()方法使用可變長度的參數列表在註冊時接受相同的參數類型。
3.1 可用參數類型
Autofac提供了幾種不同的參數匹配策略:
-
NamedParameter - 按名稱匹配目標參數
-
TypedParameter - 按類型匹配目標參數(需要精確類型匹配)
-
ResolvedParameter - 靈活的參數匹配
NamedParameter和TypedParameter只能提供常量值。
ResolvedParameter可以用作提供從容器動態檢索的值的方法,例如。 通過名稱解析服務。
3.2 帶反射組件的參數
當您解析基於反射的組件時,類型的構造函數可能需要您需要根據運行時值指定的參數,這在註冊時不可用。 您可以在Resolve()方法調用中使用一個參數來提供該值。
假設您有一個配置讀取器,需要傳遞一個配置部分名稱:
1 public class ConfigReader : IConfigReader 2 { 3 public ConfigReader(string configSectionName) 4 { 5 // 存儲配置的節點名稱 6 } 7 8 // 讀取基於節點名稱的配置 9 }
您可以將參數傳遞給Resolve()調用,如下所示:
//註冊 builder.RegisterType<ConfigReader>().As<IConfigReader>(); //解析 var reader = scope.Resolve<IConfigReader>(new NamedParameter("configSectionName", "mySectionName"));
如果您有多個參數,只需通過Resolve()方法將它們全部傳遞:
var service = scope.Resolve<AnotherService>( new NamedParameter("id", "service-identifier"), new TypedParameter(typeof(Guid), Guid.NewGuid()), new ResolvedParameter( (pi, ctx) => pi.ParameterType == typeof(ILog) && pi.Name == "logger", (pi, ctx) => LogManager.GetLogger("service")));
3.3 具有Lambda表達式組件的參數
使用lambda表達式組件註冊,您需要在lambda表達式中添加參數處理,因此當Resolve()調用傳入時,可以利用它們。
在組件註冊表達式中,您可以通過更改用於註冊的代理簽名來使用傳入參數。 而不是僅僅使用IComponentContext參數,而是接收一個IComponentContext和一個IEnumerable <Parameter>:
相關實例:
// c 是當前組件上下文 // p 是IEnumerable<Parameter>參數集合 builder.Register((c, p) =>new ConfigReader(p.Named<string>("configSectionName"))) .As<IConfigReader>();
現在,當您解析IConfigReader時,您的lambda將使用傳遞的參數:
//解析時傳參 var reader = scope.Resolve<IConfigReader>(new NamedParameter("configSectionName", "sectionName"));
參考文章:
1、https://blog.csdn.net/chiyueqi/article/details/52446569
2、http://www.yuanjiaocheng.net/Autofac/register-parameters.html
IoC之AutoFac(二)——解析服務