Autofac系列二、解析服务

摘要:
解析服务时,Autofac会自动链接服务所需的整个依赖关系链的不同级别,并解析所有依赖关系以构建完整的服务。如果您有一个未正确处理的循环依赖项或缺少必要的依赖项,则会得到DependencyResolutionException。如果您不知道服务是否已注册,则可以尝试通过ResolveOption()或TryResolve()解决它://如果IService已注册,它将被解决;如果//未注册,则返回值将为ull.varservice=scope.RevolveOptional();//如果IProvider已注册,则提供程序变量//将保留该值;otherwiseyoucantaksome//otheraction.IProviderprovider=null;如果{//Dosomething with resolvedProvidervalue.}ResolveOption()和TryResolve()本质上是为了确保特定服务已成功注册。
一、解析服务

在注册完组件并暴露相应的服务后,可以从创建的容器或其子生命周期中解析服务,让我们使用Resolve()方法来实现:

var builder = new ContainerBuilder();
builder.RegisterType<MyComponent>().As<IService>();
var container = builder.Build();

using(var scope = container.BeginLifetimeScope())
{
  var service = scope.Resolve<IService>();
}

我们应该注意到示例是从生命周期中解析服务而非直接从容器中,当然,你也应该这么做。

    有时在我们的应用中也许可以从根容器中解析组件,然而这么做有可能会导致内存泄漏。推荐你总是从生命周期中解析组件。以确保服务实例被妥善的释放和垃圾回收。

解析服务时,Autofac自动链接起服务所需的整个依赖链上不同层级并解析所有的依赖来完整的构建服务,如果你有处理不当的循环依赖或缺少了必须的依赖,你将得到一个DependencyResolutionException.

如果你不清楚一个服务是否被注册了,你可以通过ResolveOptional()或TryResolve()尝试解析:

// If IService is registered, it will be resolved; if
// it isn't registered, the return value will be null.
var service = scope.ResolveOptional<IService>();

// If IProvider is registered, the provider variable
// will hold the value; otherwise you can take some
// other action.
IProvider provider = null;
if(scope.TryResolve<IProvider>(out provider))
{
  // Do something with the resolved provider value.
}

ResolveOptional()和TryResolve()本质上都只是保证某个特定的服务已成功注册。如果该组件已注册就可以解析成功。如果解析本身失败(例如某些必需的依赖未注册),你依然会得到DependencyResolutionException。如果你不清楚服务解析本身是否会成功并需要在解析成功或失败时进行不同的操作,将Resolve()包裹在try..cath块中。

1、可使用的参数类型

 Autofac提供了多种不同的参数匹配机制:

  • NamedParameter: 通过名称匹配目标参数
  • TypeofParameter: 通过匹配目标参数(需要匹配具体的类型)
  • ResolvedParameter: 复杂参数的匹配

NamedParameter和TypeParameter只支持常量值。

ResolvedParameter 可以用于提供不同的值来从容器中动态获取对象, 例如, 通过名字解析服务

2、反射组件的参数

 当注册一个基于反射的组件时,类型的构造方法也许会需要一个无法从容器中解析出来的参数,你可以在注册时提供该值。

假如有个configuration reader需要传入一个configuration section name:

复制代码
public class ConfigReader : IConfigReader
{
  public ConfigReader(string configSectionName)
  {
    // Store config section name
  }

  // ...read configuration based on the section name.
}
复制代码

你可以使用lambda表达式组件:

builder.Register(c => new ConfigReader("sectionName")).As<IConfigReader>();

或者在反射组件注册时传参:

复制代码
// Using a NAMED parameter:
builder.RegisterType<ConfigReader>()
       .As<IConfigReader>()
       .WithParameter("configSectionName", "sectionName");

// Using a TYPED parameter:
builder.RegisterType<ConfigReader>()
       .As<IConfigReader>()
       .WithParameter(new TypedParameter(typeof(string), "sectionName"));

// Using a RESOLVED parameter:
builder.RegisterType<ConfigReader>()
       .As<IConfigReader>()
       .WithParameter(
         new ResolvedParameter(
           (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "configSectionName",
           (pi, ctx) => "sectionName"));
复制代码

3、Lambda表达式组件的参数

 使用lambda表达式组件注册,不是在注册是传入参数,而是在服务解析时传入具体的参数。

在组件注册表达式时,你可以通过改变委托签名使用传入参数进行注册,代替接收一个IComponentContext参数,一个IConpontentContext和IEnumerable<Parameter>参数:

复制代码
// 使用两个参数来注册委托
// c = The current IComponentContext to dynamically resolve dependencies
// p = An IEnumerable<Parameter> with the incoming parameter set
builder.Register((c, p) =>
                 new ConfigReader(p.Named<string>("configSectionName")))
       .As<IConfigReader>();
复制代码

当你解析IConfigReader时,你的lambda将使用这些参数来传入值:

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

1.4、不显示调用Resolve传参

Autofac支持两种功能,它们允许你自动生成支持强类型参数列表的服务“工厂”,这些参数列表会在解析时用到,这是一种创建需要参数组件实例的更清晰的方法。

  • 委托工厂 允许你定义工厂委托方法。
  • Func<T> 隐式关系类型 可以提供自动生成工厂的方法。 

2、隐式关系类型

 为了支持组件和服务之间的特殊关系,Autofac支持隐式的自动解析特定服务,想要

2.1、支持的关系类型

  • 直接依赖(B)
  • 延迟实例话(Lazy<B>)
  • 可控生命周期(OWned<B>)
  • 动态实例化(Func<B>)
  • 带参数实例化(Func<X,Y,B>)
  • 可遍历型(IEnumerable<B>,IList<B>,ICollection<B>)
  • 元数据审查(Metadata Interrogation (Meta<B>,Meta<B,X>))
  • 键控服务的查找(Keyed Service Lookup(IIndex<X,B>))

2.2、组合关系类型

2.3、关系类型和容器独立性

免责声明:文章转载自《Autofac系列二、解析服务》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇FPGA -- 实验一:闪烁灯(1)oracle创建数据库和用户、表空间,管理表空间和数据文件简介下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

依赖注入框架Autofac的简单使用

Autofac是一款IOC框架,比较于其他的IOC框架,如Spring.NET,Unity,Castle等等所包含的,它很轻量级性能上也是很高的。于是,今天抽空研究了下它。下载地址:http://code.google.com/p/autofac/downloads/list 1)解压它的压缩包,主要看到Autofac.dll,Autofac.Config...

关于使用 autoFac 的注入方法

1、使用 NUGET 安装 Autofac 2、需要引用Autofac ASP.NET MVC 5 Integration  这个扩展包。 但有时候在NuGet中找不到 该包 需要使用“程序要控制器控制台”安装 输入  安装解决 Install-Package Autofac.Mvc5 -Version 4.0.2 安装完成后引用里面就多了Aut...

AutoFac实现程序集级别的依赖注入

1、介绍 所谓程序集级别的依赖注入是指接口和实现的依赖不使用配置文件或硬代码实现(builder.RegisterType<UserInfoService>().As<IUserInfoService>();),而是通过名称约定实现依赖注入 2、项目接口及dll 2.1 项目结构(创建MVC3项目) 2.2 UI层需引入的dl...

TinyFrame升级之十:WCF Rest Service注入IOC的心

由于在实际开发中,Silverlight需要调用WebService完成数据的获取,由于之前我们一直采用古老的ASMX方式,生成的代理类不仅难以维护,而且自身没有提供APM模式的调用方式,导致在Sinverlight中实现线程同步,非常的困难。所以这里我采用了WCF Restful Service来完成。 这里我们需要新建一个WCF Rest Servic...

Autofac系列一、注册

一、注册概念 我们通过创建ContainerBuilder来注册组件并告诉容器哪些组件暴露了哪些服务。 组件可以通过反射(注册指定的.net类或开发结构的泛型)创建;通过提供现成的实例(你已创建的一个对象实例)创建,或者通过lambda表达式(一个执行实例化对象的匿名方法)来创建ContainerBuilder包含一组Register()方法来帮你实现以上...

Autofac使用

创建用例类 创建接口 namespace MyIBLL { public interface IUserBLL { void AddUser(string name, string pass); } } 一个类 namespace MyBLL { public class UserBLL:IUserBLL...