Registering Components-->Autofac registration(include constructor injection)
https://autofaccn.readthedocs.io/en/latest/register/registration.html
Registration Concepts (有4种方式来注册)
You register components with Autofac by creating a ContainerBuilder and informing the builder which components expose which services.
Components can be created via reflection (by registering a specific .NET type or open generic); by providing a ready-made instance (an instance of an object you created); or via lambda expression (an anonymous function that executes to instantiate your object). ContainerBuilder has a family of Register() methods that allow you to set these up.
Each component exposes one or more services that are wired up using the As() methods on ContainerBuilder.
// Create the builder with which components/services are registered.
var builder = new ContainerBuilder(); // Register types that expose interfaces...
builder.RegisterType<ConsoleLogger>().As<ILogger>(); // Register instances of objects you create...
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>(); // Register expressions that execute to create objects...
builder.Register(c => new ConfigReader("mysection")).As<IConfigReader>(); // Build the container to finalize registrations
// and prepare for object resolution.
var container = builder.Build(); // Now you can resolve services using Autofac. For example,
// this line will execute the lambda expression registered
// to the IConfigReader service.
using(var scope = container.BeginLifetimeScope())
{
var reader = scope.Resolve<IConfigReader>();
}
Reflection Components 第一种方式
Register by Type
Components generated by reflection are typically registered by type:
var builder = new ContainerBuilder();
builder.RegisterType<ConsoleLogger>();
builder.RegisterType(typeof(ConfigReader));
When using reflection-based components, Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container.
For example, say you have a class with three constructors like this:
public class MyComponent
{
public MyComponent() { /* ... */ }
public MyComponent(ILogger logger) { /* ... */ }
public MyComponent(ILogger logger, IConfigReader reader) { /* ... */ }
}
Now say you register components and services in your container like this:
var builder = new ContainerBuilder();
builder.RegisterType<MyComponent>();
builder.RegisterType<ConsoleLogger>().As<ILogger>();
var container = builder.Build(); using(var scope = container.BeginLifetimeScope())
{
var component = scope.Resolve<MyComponent>();
}
When you resolve your component, Autofac will see that you have an ILogger registered, but you don’t have an IConfigReader registered. In that case, the second constructor will be chosen since that’s the one with the most parameters that can be found in the container.
An important note on reflection-based components: Any component type you register via RegisterType must be a concrete type. While components can expose abstract classes or interfaces as services, you can’t register an abstract/interface component. It makes sense if you think about it: behind the scenes, Autofac is creating an instance of the thing you’re registering. You can’t “new up” an abstract class or an interface. You have to have an implementation, right?
Specifying a Constructor
You can manually choose a particular constructor to use and override the automatic choice by registering your component with the UsingConstructor method and a list of types representing the parameter types in the constructor:
builder.RegisterType<MyComponent>()
.UsingConstructor(typeof(ILogger), typeof(IConfigReader));
Note that you will still need to have the requisite parameters available at resolution time or there will be an error when you try to resolve the object. You can pass parameters at registration time or you can pass them at resolve time.
在对MyComponent进行resolve的时候,会自动进行构造函数注入。以参数最多的那个作为标准。
在实例化MyComponent的时候,发现参数ILogger已经注册了对应的类型ConsoleLogger。会自动实例化1个ConsoleLogger作为参数进行传递。
https://www.cnblogs.com/wyy1234/p/9144669.html 需要看一下这里面的评论
Instance Components 第二种方式
In some cases, you may want to pre-generate an instance of an object and add it to the container for use by registered components. You can do this using the RegisterInstance method:
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();
Something to consider when you do this is that Autofac automatically handles disposal of registered components and you may want to control the lifetime yourself rather than having Autofac call Dispose on your object for you. In that case, you need to register the instance with the ExternallyOwned method:
var output = new StringWriter();
builder.RegisterInstance(output)
.As<TextWriter>()
.ExternallyOwned();
Registering provided instances is also handy when integrating Autofac into an existing application 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:
builder.RegisterInstance(MySingleton.Instance).ExternallyOwned();
This ensures that the static singleton can eventually be eliminated and replaced with a container-managed one.
The default service exposed by an instance is the concrete type of the instance. See “Services vs. Components,” below.
Lambda Expression Components 第三种方式
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:
builder.Register(c => new A(c.Resolve<B>()));
The parameter c provided to the expression is the component context (an IComponentContext object) in which the component is being created. You can use this to resolve other values from the container to assist in creating your component. 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.
Additional dependencies can be satisfied using this context parameter - in the example, A requires a constructor parameter of type B that may have additional dependencies.
The default service provided by an expression-created component is the inferred return type of the expression.
Below are some examples of requirements met poorly by reflective component creation but nicely addressed by lambda expressions.
https://autofaccn.readthedocs.io/en/latest/register/parameters.html
第三种方式的用处在于,Passing Parameters to Register,在注册的时候需要传递参数,作为第二种实现方式。第一种方式是Parameters with Reflection Components
这个传递参数还是比较麻烦,可以考虑使用把变量插入OwinContext中,然后在需要实例化的地方,直接拿出来
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 code:
与其纠结于如何使用XML配置语法构造特定类型的值,不如使用以下代码:
builder.Register(c => new UserSession(DateTime.Now.AddMinutes()));
(Of course, session expiry is probably something you’d want to specify in a configuration file - but you get the gist 要点;))
Property Injection
While Autofac offers a more first-class approach to property injection, you can use expressions and property initializers to populate properties as well:
builder.Register(c => new A(){ MyB = c.ResolveOptional<B>() });
The ResolveOptional method will try to resolve the value but won’t throw an exception if the service isn’t registered. (You will still get an exception if the service is registered but can’t properly be resolved.) This is one of the options for resolving a service.
Property injection is not 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.
Selection of an Implementation by 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(""))
{
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.
Parameters are provided to the creation function through an optional second parameter named pin this example.
Using this registration would look like:
var card = container.Resolve<CreditCard>(new NamedParameter("accountId", ""));
A cleaner, type-safe syntax can be achieved if a delegate to create CreditCard instances is declared and a delegate factory is used.
Open Generic Components 第四种方式
Autofac supports open generic types. Use the RegisterGeneric() builder method:
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 will return an NHibernateRepository<Task>
var tasks = container.Resolve<IRepository<Task>>();
Registration of a specialized service type (e.g. IRepository<Person>) will override the open generic version.
Services vs. Components
When you register components, you have to tell Autofac which services that component exposes. By default, most registrations will just expose themselves as the type registered:
| Service | A well-defined behavioural contract shared between a providing and a consuming Component |
// This exposes the service "CallLogger"
builder.RegisterType<CallLogger>();
Components can only be resolved by the services they expose. In this simple example it means:
// This will work because the component
// exposes the type by default:
scope.Resolve<CallLogger>(); // This will NOT work because we didn't
// tell the registration to also expose
// the ILogger interface on CallLogger:
scope.Resolve<ILogger>();
You can expose a component with any number of services you like:
builder.RegisterType<CallLogger>()
.As<ILogger>()
.As<ICallInterceptor>();
Once you expose a service, you can resolve the component based on that service. Note, however, that once you expose a component as a specific service, the default service (the component type) is overridden:
// These will both work because we exposed
// the appropriate services in the registration:
scope.Resolve<ILogger>();
scope.Resolve<ICallInterceptor>(); // This WON'T WORK anymore because we specified
// service overrides on the component:
scope.Resolve<CallLogger>();
If you want to expose a component as a set of services as well as using the default service, use the AsSelf method:
builder.RegisterType<CallLogger>()
.AsSelf()
.As<ILogger>()
.As<ICallInterceptor>();
Now all of these will work:
// These will all work because we exposed
// the appropriate services in the registration:
scope.Resolve<ILogger>();
scope.Resolve<ICallInterceptor>();
scope.Resolve<CallLogger>();
builder.RegisterType<CallLogger>()
.AsSelf()
.As<ILogger>()
.As<ICallInterceptor>();
Registering Components-->Autofac registration(include constructor injection)的更多相关文章
- Ioc:Autofac Registration Concepts
Reflection Components When using reflection-based components, Autofac automatically uses the constru ...
- 一种是CI(Constructor Injection)构造方法注入,另一种是SI(Set Injection) set 注入
一:这里先说一下DI(Dependency Injection)依赖注入有种表现形式:一种是CI(Constructor Injection)构造方法注入,另一种是SI(Set Injection) ...
- spring in action学习笔记一:DI(Dependency Injection)依赖注入之CI(Constructor Injection)构造器注入
一:这里先说一下DI(Dependency Injection)依赖注入有种表现形式:一种是CI(Constructor Injection)构造方法注入,另一种是SI(Set Injection) ...
- Spring Setter Injection and Constructor Injection
Setter Injection AppContext.xml <?xml version="1.0" encoding="UTF-8"?> < ...
- [Java Sprint] Spring XML Configuration : Constructor Injection Demo
Previous we see how to do Setter injection: https://www.cnblogs.com/Answer1215/p/9472117.html Now le ...
- castle windsor学习-----Registering components by conventions
注册多个组件 1.one-by-one注册组件可能是一项非常重复的工作,可以通过Classes或Types注册一组组件(你可以指定一些特定的特征) 三个步骤 注册多个类型通常采取以下结构 contai ...
- castle windsor学习-----Registering components one-by-one 注册类型
1.在容器中注册一个类型 container.Register( Component.For<IMyService>() .ImplementedBy<MyServiceImpl&g ...
- Inversion of Control Containers and the Dependency Injection pattern
https://martinfowler.com/articles/injection.html One of the entertaining things about the enterprise ...
- 3: 组件间的依赖管理 Managing Dependencies Between Components Using the Prism Library 5.0 for WPF(英汉对照版)
Applications based on the Prism Library are composite applications that potentially consist of many ...
随机推荐
- pycharm 授权/激活
License server: http://elporfirio.com:1017/ http://idea.imsxm.com/
- java动态编译 (java在线执行代码后端实现原理)
需求:要实现一个web网页中输入java代码,然后能知道编译结果以及执行结果 类似于菜鸟java在线工具的效果:https://c.runoob.com/compile/10 刚开始从什么概念都没有到 ...
- hdu2732 (Leapin' Lizards)
题目链接:传送门 题目大意:给你 n,m n:有几行图,m是一个人最多跳m个曼哈顿距离. 给你两张图,第一张图数字为0表示没有柱子,否则有柱子且只能跳出去 x 次(x为当前字符代表的数字) 第二张图 ...
- 微信小程序入门学习-- 简易Demo:计算器
简单学习下微信小程序 官网 简易教程 · 小程序 https://mp.weixin.qq.com/debug/wxadoc/dev/ 需要通过开发者工具,来完成小程序创建和代码编辑. 下载安装,运行 ...
- jQuery初始化$(function() { }
$(document).ready(function () { }//没有双引号 $(function() { }
- 160622、详解JavaScript变量提升
变量在程序中随处可见.它们是一些始终在相互影响,相互作用的的数据和逻辑.正是这些互动使应用程序活了起来. 在JavaScript中使用变量很重要的一方面就是变量的提升 —— 它决定了一个变量何时可以被 ...
- 第二课补充01——redis-cli命令行详解、string类型、list类型、hash类型命令操作详解
一. redis-cli命令行参数 1.-x参数:从标准输入读取一个参数: [问题] [解决] 因为echo命令是默认带有回车\n的,不带回车需要echo –n命令: echo -n "ha ...
- MFC 单选按钮组向导添加和动态创建
单选按钮组的动态生成 单选按钮也属于CButton类,但由于单选按钮总是成组使用的,所以它在制作和使用上与普通按钮有一定区别. 假设有三个单选按钮组成一组,初始时,第一个单选按钮处于选中状态. 我们先 ...
- Android WebView 加载网页
通过Android 中 WebView 控件加载HTML5 页面,这是实现Android 混合开发的基础. 选择加载的网页可以是本地,也可用使远程的.需要添加访问互联网的权限:<uses-per ...
- List、Map、Set三个接口,存取元素时,各有什么特点?
List与Set都是单列元素的集合,它们有一个功共同的父接口Collection. Set里面不允许有重复的元素, 存元素:add方法有一个boolean的返回值,当集合中没有某个元素,此时add方法 ...