IoC之AutoFac(二)——解析服务

阅读目录html

 


一 Resolve方法

在您的组件注册了适当的服务后,您能够从内置的容器和子生命周期范围中解析服务。 您能够使用Resolve()方法,仍是使用上篇的例子:ide

复制代码
 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。函数

二 TryResolve和ResolveOptional方法

若是您有可能注册或可能不被注册的服务,您能够使用ResolveOptional()或TryResolve()来尝试对服务进行有条件解决:ui

复制代码
 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                 }
复制代码

三 解析服务时传参

  解析服务的时候,您可能会发现须要将参数传递给Autofac。 (若是您在注册时知道值,则能够在注册中提供它们,详细见上篇。)Resolve()方法使用可变长度的参数列表在注册时接受相同的参数类型spa

3.1 可用参数类型

Autofac提供了几种不一样的参数匹配策略:代理

  • NamedParameter - 按名称匹配目标参数code

  • TypedParameter - 按类型匹配目标参数(须要精确类型匹配)htm

  • ResolvedParameter - 灵活的参数匹配blog

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"));
相关文章
相关标签/搜索