Detailed registration Autofac

Sign concept:
we register the component by creating ContainerBuilder and tell the container which components exposed what services components can be created by reflection; creation by providing ready-made examples; or created by the lambda expression.

ContainerBuilder contains a set Register () method to help you achieve the above operation. Each module is exposed to one or more service, they use As the ContainerBuilder () method to connect together.

 1 //注册类
 2 var builder = new ContainerBuilder();
 3 
 4 builder.RegisterType<ConsoleLogger>().As<ILogger>();
 5 
 6 //注册实例
 7 
 8 var output = new StringWriter();
 9 
10 builder.RegisterInstance(output).As<TextWriter>();
11 
12 //注册lambda表达式
13 
14 builder.Register(c => new ConfigReader("mysection")).As<IConfigReader>();
15 
16 
17 var container = builder.Build();
18 
19 using(var scope = container.BeginLifetimeScope())
20 {
21   var reader = scope.Resolve<IConfigReader>();
22 }

By type registration

builder.RegisterType<ConsoleLogger>();

builder.RegisterType(typeof(ConfigReader));

When the component based on the use of the reflection, Autofac automatically find construction method has the most matching parameters from the container for your class.

Constructor specifies
you can use the methods and constructors UsingConstructor series of parameters representative of the type to manually specify a type constructor

builder.RegisterType<MyComponent>().UsingConstructor(typeof(ILogger), typeof(IConfigReader));

By instance registration:

Sometimes you might want to use and add it to the vessel for registration component generates an object instance in advance:

var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();

When you do this you need to consider a few things, Autofac handled automatically registered release components, you might want to control their own life cycle rather than letting Autofac to help you release your call to Dispose of objects. In this case, you You need to register instances by ExternallyOwned method:

var output = new StringWriter();
builder.RegisterInstance(output)
.As<TextWriter>().ExternallyOwned();

Register by Lambda expressions:
Using the registration component type Normally, however, when the component is created are no longer simply call the constructor method, you need to use Lambda expressions
Autofac to receive a delegate or lambda expression, used as a component Creator:

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

Expression parameter c is provided a context component (a IComponentContext object), which is created in the assembly. You can use this parameter to other values ​​parsed from the vessel to help create your components. This parameter is used instead of a closure to access to the container is very important so you can ensure accurate release the object and can be a good support nested containers.

Satisfy the other parameters using the context dependent successfully introduced - e.g., A requires a constructor parameter B, which may have other dependencies.

Complex parameters

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

Injection parameters, you can use an expression to fill the initialization parameters and properties:

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

ResolveOptional method tries to resolve, but if the service is not registered, will not throw an error. (If the service successfully registered but can not be resolved successfully, you will still get an error.) This is a way to resolve the service.

Not recommended in most cases the injection parameters. The other objects such as empty mode, the reload constructor or default values ​​for these parameters manner, by injection constructor to create an alternative relies more refreshing, "immutable" component.

The selection of a particular parameter value is achieved by
creating a separate component is a specific type of major benefit can be varied typically specify a particular type can be done at runtime, rather than during the configuration:.
Builder.Register <CreditCard> (
(C, P) =>
{
var = an accountId p.Named <String> ( "an accountId");
IF (accountId.StartsWith ( ". 9"))
{
return new new A GoldCard (an accountId);
}
the else
{
return new new StandardCard (an accountId );
}
});

Example, CreditCard two class implements, GoldCard and StandardCard - which classes are instantiated depending on account ID provided during runtime.
Creation parameter by a second method of example p optional parameter passed.
Can parse such:

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

If you declare a delegate CreditCard instance is created and commissioned a plant, it can become more clean syntax, type-safe.

Sign generic components
Autofac support open generic use RegisterGeneric () method:

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

When the container is a type of service that matches the request, Autofac will find embodied closed type corresponding to:

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

 

Exposing services:
registration component, we have to tell Autofac, components exposed what services they expose themselves by default, in most cases when the registration type:

builder.RegisterType<CallLogger>();

You can make a component exposed to any number of services:

builder.RegisterType<CallLogger>()
.As<ILogger>()
.As<ICallInterceptor>();

After exposure to the service, you can resolve the components of the service of the Note, however, once you expose the components for a particular service, the default service (component type) will be covered:

scope.Resolve<ILogger>();
scope.Resolve<ICallInterceptor>();

// This WON'T WORK anymore because we specified
// service overrides on the component:
scope.Resolve<CallLogger>();

If you only want to expose a series of specific components of service, want to expose it to the default service, you can use AsSelf method:

builder.RegisterType<CallLogger>()
.AsSelf()
.As<ILogger>()
.As<ICallInterceptor>();

All this can be resolved on the success:

scope.Resolve<ILogger>();
scope.Resolve<ICallInterceptor>();
scope.Resolve<CallLogger>();

Sign default, if more than one component exposed to the same service, Autofac will use components last registered as a provider of services:

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

 

The example above, FileLogger will ILogger as the default service provider because it is the last to be registered.
Want to override this behavior, use PreserveExistingDefaults () method to modify:
. Builder.RegisterType <ConsoleLogger> () of As <ILogger> ( );
builder.RegisterType <the FileLogger> () of As <ILogger> () PreserveExistingDefaults ()..;

The example above, ConsoleLogger will ILogger as the default service provider since the last registration FileLogger used PreserveExistingDefaults ().
Registration conditional
notes
registered conditional self Autofac 4.4.0 introduced
in most cases, as to override the default as above registration is already enough for us to successfully resolve the correct components at run time we can use PreserveExistingDefaults () to ensure that components are registered in the correct order; for complex conditions and actions we can take advantage of a lambda expression / delegate registration process . very good
but still should be some scenes you do not want to encounter:
you do not want some of the functionality of a component will appear in the case of normal operation in the program, for example, if you parse the IEnumerable <T> service (. a bunch of services), all of the registered components to achieve these services will be returned, regardless of whether you use PreserveExistingDefaults (). in most cases this is also OK, but in some extreme cases, you do not want that.
you just just want to register a component in some other cases components are not registered; or just In some other cases components have been registered. You do not resolve from the container out of things you do not want, and you do not have to modify the container has been created. Can be conditional on other registration component registration is very easy to use .
here are two easy registration extension method:
onlyif () - provides an expression, the use of a registered IComponentRegistry to decide whether to take place.
IfNotRegistered () - a quick way to prevent the occurrence of registration under other circumstances service has been registered .
These methods are performed when ContainerBuilder.Build () and the actual execution order registered component following are some examples to show how they work:.
Var Builder new new ContainerBuilder = ();

builder.RegisterType<ServiceA>()
.As<IService>();
builder.RegisterType<ServiceB>()
.As<IService>()
.IfNotRegistered(typeof(IService));


builder.RegisterType<HandlerA>()
.AsSelf()
.As<IHandler>()
.IfNotRegistered(typeof(HandlerB));
builder.RegisterType<HandlerB>()
.AsSelf()
.As<IHandler>();
builder.RegisterType<HandlerC>()
.AsSelf()
.As<IHandler>()
.IfNotRegistered(typeof(HandlerB));


builder.RegisterType<Manager>()
.As<IManager>()
.OnlyIf(reg =>
reg.IsRegistered(new TypedService(typeof(IService))) &&
reg.IsRegistered(new TypedService(typeof(HandlerB))));


container was builder.Build = ();

Configuration register
you can use XML or programming or configuration of formula ( "modules") to provide a group registration or registration change at run time. For some dynamic logic register or register generating conditions, you can use Autofac module.
dynamic registration provides
the easiest way is to introduce dynamic registration module Autofac logic or simply cut function. For example, you can use a module dynamically attach a log4net logger instance on the parsed service.
If you want to achieve a more dynamic operation , such as adding new implicit relationship between the type of support, you can view the registered source module in advanced concepts chapter.

 

Guess you like

Origin www.cnblogs.com/fanfan-90/p/12014055.html