Autofac之自动装配

从容器中的可用服务中选择一个构造函数来创造对象,这个过程叫做自动装配。这个过程是通过反射实现的

默认

思考这么一个问题,如果注册类型中存在多个构造函数,那么Autofac会选择哪一个来创建类型的实例

答案是"尽可能最多参数"

class ConstructorClass
{private Class1 _clas1;private Class2 _clas2;private Class3 _clas3 = null;public ConstructorClass(){_clas1 = null; _clas2 = new Class2 { Id = -1 };}public ConstructorClass(Class1 clas1, Class2 clas2){_clas1 = clas1; _clas2 = clas2;}public ConstructorClass(Class2 clas2, Class3 clas3){_clas2 = clas2; _clas3 = clas3;}public ConstructorClass(Class2 clas2, Class3 clas3, Guid guid){_clas1 = new Class1 { Id = guid }; _clas2 = clas2; _clas3 = clas3;}public ConstructorClass(Class1 clas1, Class2 clas2, Class3 clas3){_clas1 = clas1; _clas2 = clas2; _clas3 = clas3;}public override string ToString(){return string.Format("{{Class1.Id: {0}, Class2.Id: {1}, Class3: {2}}}",_clas1 == null ? "null" : _clas1.Id.ToString(),_clas2 == null ? "null" : _clas2.Id.ToString(),_clas3 == null ? "null" : "not null");}
}class Class1
{public Guid Id { get; set; }
}class Class2
{public int Id { get; set; }
}class Class3
{}static void Main(string[] args)
static void Main(string[] args)
{//注册容器var builder = new ContainerBuilder();//向容器中注册类型builder.RegisterType<ConstructorClass>();builder.RegisterType<Class2>();builder.RegisterType<Class3>();using (var container = builder.Build()){#region Resolve对象构造方法选择原则(当我们注册的类型拥有多个构造方法,那么在Resolve时,将会以尽可能最多参数构造方法为准)var obj = container.Resolve<ConstructorClass>();Console.WriteLine(obj);#endregion
    }Console.ReadKey();
}

该实例显示,选择的是第三个构造函数,参数为(Class2 clas2, Class3 clas3),

按照字面上里说明”最多参数“,那么理应执行的是最后一个构造方法或倒数第二个构造方法,但是为什么却是第三个,这也就是为什么我要加“尽可能”三字了。

先抛开为什么执行的第三个构造方法,我们还是会有疑问”如果执行的是第三个构造方法,那么Class2和Class3参数分别赋的是什么值?值又是从哪儿来?“,这里就涉及到了后面会讲到的构造注入。我们可以看到,在进行类型注册时,我们是对Class2和Class3进行了注册的,而ConstructorClass又是通过Autofac进行获取的,所以Class2和Class3参数的值是由Autofac进行初始化赋值的,Class2和Class3没有自定义构造方法,所以调用的是默认的空构造方法。

在知道Class2和Class3参数的初始化与赋值缘由后,我们再来看看之前的那个问题,为什么会执行第三个构造方法,其实现在就好明白了,因为最后两个的构造方法,一个需要额外的Guid类型参数,另一个需要Class1类型参数,而这两个类型又没有经过注册,如果调用这两个构造方法,那么Auotofac将不知道应该赋何值给这两个参数,所以Autofac最终选择了第三个构造方法。

此时我把第三个构造函数注释掉之后,会调用第一个构造函数,按照"尽可能最多参数"原则,此时不应该调用第二个吗?答案是,Autofac会在已注册的类型中寻找,虽然Class2类型被注册,第二个构造函数Class1类型参数Autofac不知道如何赋值,所以选择了默认的构造函数,如果在容器中注册类型Class1取消掉类型Class3的注册,此时就会调用第二个构造函数.(Autofac寻找构造函数的规则是在已注册的类型中寻找参数完全匹配的构造函数)

UsingConstructor:指定使用某个构造函数

通过上面的例子我们知道Autofac创建类型实例时会默认从容器中选择匹配参数最多的构造函数,此时在容器中将Class1、Class2、Class3类型都注册,此时默认情况会使用最后一个构造函数,如果如果想要选择一个不同的构造函数,就需要在注册的时候就指定它,此时指定使用参数为(Class1 clas1, Class2 clas2)的构造函数

builder.RegisterType<Class1>();
builder.RegisterType<Class2>();
builder.RegisterType<Class3>();
builder.RegisterType<ConstructorClass>().UsingConstructor(typeof(Class1), typeof(Class2));

 额外的构造函数参数

有两种方式可以添加额外的构造函数参数,在注册的时候和在检索的时候。在使用自动装配实例的时候这两种都会用到。

注册时添加参数

使用WithParameters()方法在每一次创建对象的时候将组件和参数关联起来。

builder.RegisterType<ConstructorClass>().WithParameter("guid", Guid.NewGuid());
//builder.RegisterType<Class1>();//将Class1注册因为在尽可能最多的原则上,出现了两个最多参数的构造方法,Autofac不知道应该选择哪个进行执行
builder.RegisterType<Class2>();
builder.RegisterType<Class3>();

在检索阶段添加参数
在Resolve()的时候提供的参数会覆盖所有名字相同的参数,在注册阶段提供的参数会覆盖容器中所有可能的服务。

var obj = container.Resolve<ConstructorClass>(new NamedParameter("guid", Guid.NewGuid()));

 自动装配

在需要的时候,依然可以创建指定的构造函数创建指定的类。

builder.Register(c => new Clas1());

Resolve的方法签名为:Resolve<T>(this IComponmentContext context, params Parameter[] parameters)

第一个参数也就是我们使用的container,我们主要关注第二个参数——一个可变的Parameter数组,Parameter是一个抽象类,其中NamedParameter为Parameter的一个子类,除了NamedParameter,还有以下几种子类拱Resolve时使用:

参数类型

参数说明

NamedParameter

根据名称进行匹配

PositionalParameter

根据索引进行匹配,注意:起始索引为0

TypedParameter

根据类型进行匹配,注意:传入多个相同类型的TypedParameter,所有该类型的参数都将采用第一个TypedParameter的值

ResolvedParameter

接收两个Func参数,两个Func签名都接收两个相同的参数ParameterInfo和IComponmentContext,第一个参数为参数的信息(常使用放射的朋友应该熟悉),第二个参数还是当做IContainer使用就好了。第一个Func的返回值为bool,表明当前这个ResolvedParameter是否使用当前匹配到的参数,如果返回true,则会执行第二个Func;第二个Func返回一个object对象,用于填充构造参数值。

 

下面有一个这些Parameter使用的示例供参考:

复制代码
class Program
{static void Main(string[] args){var builder = new ContainerBuilder();builder.RegisterType<ParameterClass>();var container = builder.Build();container.Resolve<ParameterClass>(new NamedParameter("value", "namedParameter"),      //匹配名字为value的参数new TypedParameter(typeof (int), 1),                //匹配类型为int的参数new PositionalParameter(4, "positionalParameter"),  //匹配第五个参数(注意,索引位置从0开始)new TypedParameter(typeof (int), -1),               //这个将被抛弃,因为前面已经有一个类型为int的TypedParameternew ResolvedParameter(//第一个Func参数用于返回参数是否符合要求,这里要求参数是类,且命名空间不是System开头,所以第四个参数将会匹配上(pi, cc) => pi.ParameterType.IsClass && !pi.ParameterType.Namespace.StartsWith("System"),//第二个Func参数在第一个Func执行结果为true时执行,用于给参数赋值,也就是第四个参数的值为这个Func的执行结果(pi, cc) => new Temp {Name = "resolveParameter"}));// 最后的输出结果为: {x:1, y:1, value:'namedParameter', temp.Name:'resolveParameter', obj:'positionalParameter'}Console.Write("Press any key to continue...");Console.ReadKey();}
}class ParameterClass
{public ParameterClass(int x, int y, string value, Temp temp, object obj){Console.WriteLine("{{x:{0}, y:{1}, value:'{2}', temp.Name:'{3}', obj:'{4}'}}", x, y, value, temp.Name, obj);}
}class Temp
{public string Name { get; set; } 
}
复制代码

转载于:https://www.cnblogs.com/GnailGnepGnaw/p/10757340.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/279628.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对Emlog 6.0 Beta的完整代码审计过程

Emlog 6.0 beta版本&#xff0c;这可能是最后一篇关于PHP语言CMS的代码审计文章&#xff0c;此次将详细记录完整的审计过程。 文章基本上完整记录小东的对此CMS审计过程&#xff0c;或许显得繁琐&#xff0c;但代码审计的过程就是这样&#xff0c;发现可能项&#xff0c;然后精…

SINOCES 2011

突然发现又好久没写过日志了 是在是太懒了… 难得休假去看了眼消费电子 感觉实在是一年不如一年 佳能、索尼不见踪影&#xff0c;相机满场没见一家&#xff08;大牌子是真没见到&#xff09; 华硕技嘉微星等主板厂商同样失踪… PC方面&#xff0c;联想貌似是来卖电脑包鼠标的&a…

esim卡与ms卡的区别_什么是eSIM,它与SIM卡有何不同?

esim卡与ms卡的区别With the launch of the Apple Watch 3, the term “eSIM” has been thrown around a lot. And now, Google’s Pixel 2 is the first phone to use this new technology, it’s time we take a closer look at what it is, what it does, and what this me…

机器学习实战之logistic回归分类

利用logistic回归进行分类的主要思想&#xff1a;根据现有数据对分类边界建立回归公式&#xff0c;并以此进行分类。 logistic优缺点&#xff1a; 优点&#xff1a;计算代价不高&#xff0c;易于理解和实现。缺点&#xff1a;容易欠拟合&#xff0c;分类精度可能不高。 .适用数…

HDU 6343.Problem L. Graph Theory Homework-数学 (2018 Multi-University Training Contest 4 1012)

6343.Problem L. Graph Theory Homework 官方题解: 一篇写的很好的博客: HDU 6343 - Problem L. Graph Theory Homework - [(伪装成图论题的)简单数学题] 代码: 1 //1012-6343-数学2 #include<iostream>3 #include<cstdio>4 #include<cstring>5 #include<…

Android GridView LruCache

照片墙这种功能现在应该算是挺常见了&#xff0c;在很多应用中你都可以经常看到照片墙的身影。它的设计思路其实也非常简单&#xff0c;用一个GridView控件当作“墙”&#xff0c;然后随着GridView的滚动将一张张照片贴在“墙”上&#xff0c;这些照片可以是手机本地中存储的&a…

如何在Android TV上自定义推荐行

When you fire up Android TV, the first thing you see is a list of movies and shows the system thinks you’ll like. It’s often full of the latest flicks or hottest news, but sometimes it could just be things relevant to your interests and the apps you have…

steam串流到手机_如何从手机将Steam游戏下载到PC

steam串流到手机Steam allows you to remotely install games from your smartphone, just like you can with a PlayStation 4 or Xbox One. You can download games to your gaming PC from anywhere, ensuring those big downloads are complete and the game is ready to p…

禁用windows10更新_如何在Windows 10中禁用投影

禁用windows10更新The drop shadows on applications in the Windows 10 preview are really big and suspiciously similar to the ones in OS X, and if they aren’t your speed, you can easily remove them. We actually think they look good, but since somebody out th…

如何访问 Service?- 每天5分钟玩转 Docker 容器技术(99)

前面我们已经学习了如何部署 service&#xff0c;也验证了 swarm 的 failover 特性。不过截止到现在&#xff0c;有一个重要问题还没有涉及&#xff1a;如何访问 service&#xff1f;这就是本节要讨论的问题。 为了便于分析&#xff0c;我们重新部署 web_server。 ① docker se…

Linux配置手册(二)配置DHCP服务器

1.检查是否安装DHCP服务器软件 2.挂在RHEL5系统光盘 3.安装DHCP服务软件 4.将模板配置文件复制并覆盖现在的配置文件 5.配置修改dhcpd.conf文件 配置信息 默认租约时间 default-lease-time 最大租约时间 max-lease-time 局域网内所有主机的域名 option domain-name 客户机所使用…

什么是Google Play保护以及如何确保Android安全?

Android is open, flexible, and all about choice. Unfortunately, that flexibility comes more potential security issues. The good news is that Google has a system in place named Play Protect that helps keep Android secure. Android开放&#xff0c;灵活且具有多…

如何使计算机为您读取文档

Since the beginning of the computer age, people have always enjoyed making computers talk to them. These days, that functionality is built right into Windows and you can easily use it to have your PC read documents to you. 自计算机时代开始以来&#xff0c;人…

面试中常问的List去重问题,你都答对了吗?

2019独角兽企业重金招聘Python工程师标准>>> 面试中经常被问到的list如何去重&#xff0c;用来考察你对list数据结构&#xff0c;以及相关方法的掌握&#xff0c;体现你的java基础学的是否牢固。 我们大家都知道&#xff0c;set集合的特点就是没有重复的元素。如果集…

Coolite Toolkit学习笔记五:常用控件Menu和MenuPanel

Coolite Toolkit里的Menu控件和其他的.NET Web控件不一样&#xff0c;如果只是设计好了Menu或是通过程序初始化菜单项&#xff0c;菜单是不会呈现在界面上的&#xff0c;因为Coolite Toolkit规定Menu控件需要一个容器来做依托&#xff0c;而这个让Menu依托的控件就是MenuPanel&…

windows命令提示符_如何个性化Windows命令提示符

windows命令提示符Command line interfaces can be downright boring and always seem to miss out on the fresh coats of paint liberally applied to the rest of Windows. Here’s how to add a splash of color to Command Prompt and make it unique. 命令行界面可能非常…

android-api28转换到api19-不能编译

安装出现错误- rootponkan:/ # pm install /mnt/usb/sda1/app-debug.apkpkg: /mnt/usb/sda1/app-debug.apk Failure [INSTALL_FAILED_OLDER_SDK]查看系统和api版本 rootponkan:/ # getprop ro.build.version.release 5.1.1 rootponkan:/ # getprop ro.build.version.sdk 22将ap…

Java多线程编程 — 锁优化

2019独角兽企业重金招聘Python工程师标准>>> 阅读目录 一、尽量不要锁住方法 二、缩小同步代码块&#xff0c;只锁数据 三、锁中尽量不要再包含锁 四、将锁私有化&#xff0c;在内部管理锁 五、进行适当的锁分解 正文 并发环境下进行编程时&#xff0c;需要使用锁机…

Android Ap 开发 设计模式第六篇:原型模式

Prototype Pattern 名称由来 不是利用类来产生实例对象&#xff0c;而是从一个对象实例产生出另一个新的对象实例 &#xff0c;根据被视为原型的对象实例 &#xff0c;建立起的另一个新的对象实例就称为原型模式&#xff08;Ptototype Pattern&#xff09;。 需求场景 种类过多…

netty实现客户端服务端心跳重连

前言&#xff1a; 公司的加密机调度系统一直使用的是http请求调度的方式去调度&#xff0c;但是会出现网络故障导致某个客户端或者服务端断线的情况&#xff0c;导致很多请求信息以及回执信息丢失的情况&#xff0c;接着我们抛弃了http的方式&#xff0c;改为Tcp的方式去建立客…