[Autofac]组件创建

  ComponentCreation组件创建   
The container provides several built in options to create components  

Autofac中的容器提供几个内置的选项来创建组件。
FeaturedAutofac2

Updated   Aug 16, 2010  by   nicholas...@gmail.com

Components can be created using lambda expressions, by reflection, or by providing a ready-made instance. ContainerBuilder provides theRegister() family of methods to set this up.

可以使用lambda表达式,反射或者提供现存的实例来创建组件。ContainerBuilder提供了一系列重载的Register方法来做这个事情。

Components are wired to services using the As() methods on ContainerBuilder:

组件通过使用ContainerBuilderAS方法绑定到服务:

var builder = new ContainerBuilder();

builder.RegisterType<ConsoleLogger>().As<ILogger>();

builder.RegisterType<NHPersonRepository>()
    .As<IFindPerson, IRepository<Person>>();

Using As() in a component registration overrides the default service for that component, so:

在组件注册中使用As方法会重写组件的默认服务,所以

container.Resolve<ILogger>();

will succeed in the above scenario, but:

在上面的场景中将成功,

container.Resolve<ConsoleLogger>();

will not.  不会。

Reflection 反射

Autofac is capable of inspecting a type, choosing an appropriate constructor, and creating an instance through reflection. The RegisterType<T>() and RegisterType(Type) methods set a component up this way:

Autofac 可以检测类型、 选择适当的构造函数,并通过反射来创建实例。组件可以通过使用RegisterType<T>() 和RegisterType(Type)的方式来创建。

builder.RegisterType<A>();  // Create A using reflection
builder.RegisterType(typeof(B)); // Non-generic version

The process of choosing a constructor and instantiating dependencies is discussed further in Autowiring.

选择构造函数并实例化依赖关系将在自动装配章节进行进一步讨论。

Default Service 默认服务

The default service for reflection-created components is the implementation type (A above will provide the service A.)

通过反射创建组件的默认服务是注册类型的实例 (上面A将提供服务A)。

Expressions 表达式

Reflection is a pretty good default choice for component creation. Things get messy though when component creation logic goes beyond a simple constructor call.

对于组件创建来说,反射是一个很好的默认选择。但是当组件的创建逻辑不只是简单的调用构造函数时,事情就变得很复杂。

Autofac can accept a delegate or lambda expression to be used as a component creator:

Autofac可以接收委托或者是lambda表达式来作为组件的创建者:

builder.Register(c => new A(c.Resolve<B>()));

The parameter c provided to the expression is the container in which the component is being created. It is important to use this rather than a closure to access the container so that deterministic disposal and nested containers can be supported correctly.

提供给表达式的参数c是在其中创建该组件的容器重要的是使用这种方式,而不是通过闭包访问容器,这样便可以正确支持确定性清理容器和嵌套容器。

Additional dependencies can be satisfied using this parameter - in the example, A requires a constructor parameter of type B.

在此示例中,附加依赖项使用此参数得到满足- A的构造函数参数需要类型B

Below are examples of some requirements met poorly by reflective component creation.

下面是一些比较少见的通过反射创建组件的例子。

Complex Parameters 复杂参数

Constructor parameters can't always be declared with simple constant values. Rather than puzzling over how to construct a value of a certain type using an XML configuration syntax, use C#:

构造函数的参数不能总是用简单常量来声明。与其使用令人费解的XML 配置语法来创建某个类型的值,不如使用 C#

builder.Register(c => new UserSession(DateTime.Now.AddMinutes(25)));

(Of course, session expiry is probably something you'd want to specify in a configuration file - but you get the gist ;))

当然,会话终止可能是你想要在一个配置文件中指定的事情 - 但你确实可以这样做。

Property Injection 属性注入

The preferred approach is to use property initialisers for this. The IComponentContext.ResolveOptional() method can be handy:

首选的方法是使用属性初始化来实现。 IComponentContext.ResolveOptional()方法可以很方便完成此任务

builder.Register(c => new A(){ MyB = c.ResolveOptional<B>() });

Alternatively, the PropertiesAutowired() configuration method will cause property injection:

另外,使用PropertiesAutowired() 配置方法也会导致属性注入:

builder.RegisterType<X>().PropertiesAutowired();

Property injection is not, however, recommended in the majority of cases. Alternatives like the Null Object pattern, overloaded constructors or constructor parameter default values make it possible to create cleaner, "immutable" components with optional dependencies using constructor injection.

但是在大部分情况下都不推荐使用属性注入。替代方案如使用Null Object模式,重载构造函数或者构造函数参数的默认值,通过构造注入创建一个简洁的,稳定的,带有任意依赖关系的组件成为可能。

Selection of an Implementer based on a Parameter Value

基于参数值来选择服务提供者

One of the great benefits of isolating component creation is that the concrete type can be varied. This is often done at runtime, not just configuration time:

由于组件的实现是各种各样的类型,所以最好抽离组件的创建过程。这通常在运行阶段来实现,而不是仅仅是配置阶段:

builder.Register<CreditCard>((c, p) => {
    var accountId = p.Named<string>("accountId");
    if (accountId.StartsWith("9"))
      return new GoldCard(accountId);
    else
      return new StandardCard(accountId);
  });

In this example, CreditCard is implemented by two classes, GoldCard and StandardCard - which class is instantiated depends on the account id provided at runtime.

这此个示例中,CreditCard GoldCard StandardCard 2个实现类,实例化那个类取决于运行时提供的账户ID

Parameters are provided to the creation function through an optional second parameter named p in this example.

在这个示例这种,构造函数获取了一个可选的参数NamedParameter p。

Using this registration would look like:

以使用如下面的方式来注册获取组件实例:

var card = container.Resolve<CreditCard>(new NamedParameter("accountId", "12345"));

A cleaner, type-safe syntax can be achieved if a delegate to create CreditCards is declared and a delegate factory is used.

如果使用委托或者委托工厂来创建CreditCards实例,可以使语法更简洁,而且它是类型安全的。

Default Service 默认服务

The default service provided by an expression-created component is the inferred return type of the expression.

表达式创建的默认服务的组件实例是通过表达式的返回类型推断出来的。

Provided Instances 提供实例

When integrating Autofac into an existing application there will sometimes be cases where a singleton instance already exists and needs to be used by components in the container. Rather than tying those components directly to the singleton, it can be registered with the container as an instance:

在现有的应用程序中使用Autofac时,如果一个单例是在容器外创建完成,容器中的组件却需要使用它,有时这会产生许多问题。与其直接把那些容器中的组件绑定到这个单例,不如它注册到容器中。

builder.RegisterInstance(MySingleton.Instance).ExternallyOwned();

This ensures that the static singleton can eventually be eliminated and replaced with a container-managed one.

这样可以确保这个静态单例被容器中的托管单例所取代。

Default Service 默认服务

The default service exposed by an instance is the concrete type of the instance.

默认服务公开的实例就是注册的具体类型的实例。

Open Generic Types 泛型

Autofac supports open generic types. Use the RegisterGeneric() builder method:

Autofac通过使用builder RegisterGeneric方法来支持泛型:

builder.RegisterGeneric(typeof(NHibernateRepository<>))
  .As(typeof(IRepository<>))
  .InstancePerLifetimeScope();

When a matching service type is requested from the container, Autofac will map this to an equivalent closed version of the implementation type:

当从容器中请求一个匹配的服务类型时,Autofac会自动匹配一个等效的封闭实现类型:

// Autofac will return an NHibernateRepository<Task>
var tasks = container.Resolve<IRepository<Task>>();

Registration of a specialised service type (e.g. IRepository<Person>) will override the open generic version.

册一个具体的的服务类型(例如IRepository<Person>)会覆盖注册的此泛型版本。

Default Registrations 默认注册

If more than one component exposes the same service, Autofac will use the last registered component as the default provider of that service.

如果不只一个组件公开相同的服务,Autofac会使用最后注册的组件作为默认服务的提供者。

To override this behaviour, use the PreserveExistingDefaults() modifier:

可以使用PreserveExistingDefaults()修饰符来重写此行为:

builder.Register<X1>().As<IX>();
builder.Register<X2>().As<IX>().PreserveExistingDefaults();

In this scenario, X1 will be the default for IX (without the PreserveExistingDefaults() modifier, X2 would be the default because it is registered last.)

此场景中,X1会是IX的默认服务提供者(如果没有使用PreserveExistingDefaults()修饰符,X2会是默认服务提供者,因为它最后一个注册)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值