从容器中的可用服务中, 选取一个构造函数来创造对象, 这个过程就是自动装配.

一、选择构造函数

默认情况下, autofac会使用无参构造函数, 去创建对象. 我将Person类稍微修改了下.

public interface IPerson
{
void Self();
} public class Person : IPerson
{
IAnimal adopt; public string Name { get; set; } public int Age { get; set; } public Person()
{
Console.WriteLine("无参构造函数");
} public Person(IAnimal MyPerson)
{
Console.WriteLine("一个参数构造函数");
adopt = MyPerson;
} public Person(string name, int age)
{
Console.WriteLine("两个参数构造函数");
this.Name = name;
this.Age = age;
} public void Self()
{
Console.WriteLine("我叫{0}, 今年{1}岁了!", this.Name, this.Age);
} public void Say()
{
Console.WriteLine("我领养了一只小动物");
adopt.Say();
}
}

但是也可以通过传入参数的方式, 去自动选择使用哪一个构造函数. 还可以在注册的时候就指定使用哪一个构造函数.

builder.RegisterType<Person>();

//-------------------------------------------------
var person = container.Resolve<Person>();
person.Self(); var personA = container.Resolve(typeof(Person), new NamedParameter("name", "elvin"), new NamedParameter("age", )) as Person;
personA.Self();

这种方式, 就是通过传参来控制调用哪一个构造函数, 其内部是通过反射的方式去实现的.

如果使用UsingConstructor指定了要使用的构造函数, 就不能使用上面的无参方式去实现了, 会报错的.

builder.RegisterType<Person>().UsingConstructor(typeof(string), typeof(int));
//-------------------------------------------------
//var person = container.Resolve<Person>(); 这种方式就会报错
//person.Self(); var personA = container.Resolve(typeof(Person), new NamedParameter("name", "elvin"), new NamedParameter("age", )) as Person;
personA.Self();

有图有真相哦.

二、额外的构造函数参数

添加构造函数, 有两个地方可以添加, 一个是在注册的时候添加, 另一个是Resolve的时候添加, 就如同上面这个例子中的personA一样的.

那下面就来说一说注册的时候添加吧.

builder.RegisterType<Person>().WithParameters(new NamedParameter[] { new NamedParameter("name", "sniper"), new NamedParameter("age", ) });

//-------------------------------------------------
var person = container.Resolve<Person>();
person.Self(); var personA = container.Resolve(typeof(Person), new NamedParameter("name", "elvin"), new NamedParameter("age", )) as Person;
personA.Self();

这个时候, 我发现, 无参的写法和有参的写法, 都不会报错, 而且, 在创建实例的时候, 都是调用的两个参数的构造函数

如果这个时候, 我使用一个参数的方式去写

var personB = container.Resolve(typeof(Person), new NamedParameter("MyPerson", new Dog() { Name = "小花" })) as Person;
personB.Self();

这个时候, 会发现, autofac完全没有理我, 还是用的之前约定的那个构造函数. 真调皮.

这种在注册时约定参数的方式, 感觉跟注册实例的方式很像, 为了解答我的疑惑, 不得不亲自试验一遍.

builder.RegisterInstance<Person>(new Person("liang", ));
//-------------------------------------------------
var person = container.Resolve<Person>();
person.Self();
person.Age += ; var personA = container.Resolve(typeof(Person), new NamedParameter("name", "elvin"), new NamedParameter("age", )) as Person;
personA.Self();
person.Age += ; var personB = container.Resolve(typeof(Person), new NamedParameter("MyPerson", new Dog() { Name = "小花" })) as Person;
personB.Self();

从这里看到, 虽然都是在注册时, 给了构造函数的约定, 但是还是有天差地别的. 注册实例的方式有点类似于单例.

三、自动装配

通过程序集扫描的方式, 可以自动装配, 省去许多配置的工作和重复的工作

builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces();
//-------------------------------------------------
var person = container.Resolve<IPerson>();
person.Self(); var personA = container.Resolve<Person>();
personA.Self(); var animal = container.Resolve<IAnimal>();
animal.Say();

这里为什么会调用一个参数的构造函数呢, 为此我修改了Cat类, 加入了两个构造函数, 一个无参, 一个string name参数, 发现调用的时候, Cat这里还是无参的构造函数.

然后我又修改了Person的一个参数的构造函数, 将参数改为string name, 运行之后发现调用的就是无参的构造函数了, 从这些现象来看, 影响到autofac选择构造函数的, 应该就是 IAnimal 这个了. 然后我又加了一个三参构造函数, Person(IAnimal myPerson, string name, int age), 发现还是调用的无参构造函数.

builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces(); //-------------------------------------------------
var person = container.Resolve<IPerson>();
person.Self();

我大致看了一下源码

这个方法中, 程序会根据参数去查找是否有容器中的参数, 如果有的话, 会选择使用匹配上的构造函数, 这里有一个原则, 就是使用匹配个数最多的那个构造函数, 但是这个构造函数又要做到参数尽可能的少. 是不是有点晕, 给个例子就清晰了

public Person(string name)
{
Console.WriteLine("一个参数name构造函数");
this.Name = name;
}
public Person(IAnimal MyPerson)
{
Console.WriteLine("两个参数IAnimal, IGo构造函数");
adopt = MyPerson;
} public Person(IAnimal MyPerson, IGo go)
{
Console.WriteLine("两个参数IAnimal, IGo构造函数");
adopt = MyPerson;
this.go = go;
} public Person(IAnimal myPerson, string name, int age)
{
Console.WriteLine("三个参数构造函数");
this.Name = name;
this.Age = age;
adopt = myPerson;
} public Person(IAnimal myPerson, IGo go, string name, int age)
{
Console.WriteLine("四个参数构造函数");
this.Name = name;
this.Age = age;
adopt = myPerson;
this.go = go;
}

ok, 自动匹配规则已经浮出水面了

Autofac - 装配的更多相关文章

  1. Autofac 组件、服务、自动装配 《第二篇》

    一.组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1.类型创建RegisterType AutoFac能够通过反射检查一个类型,选择 ...

  2. Autofac 组件、服务、自动装配(2)

    一.组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1.类型创建RegisterType AutoFac能够通过反射检查一个类型,选择 ...

  3. Autofac之自动装配

    从容器中的可用服务中选择一个构造函数来创造对象,这个过程叫做自动装配.这个过程是通过反射实现的 默认 思考这么一个问题,如果注册类型中存在多个构造函数,那么Autofac会选择哪一个来创建类型的实例 ...

  4. Autofac 组件、服务、自动装配

    一.组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1.类型创建RegisterType AutoFac能够通过反射检查一个类型,选择 ...

  5. Autofac - MVC/WebApi中的应用

    Autofac前面写了那么多篇, 其实就是为了今天这一篇, Autofac在MVC和WebApi中的应用. 一.目录结构 先看一下我的目录结构吧, 搭了个非常简单的架构, IOC(web), IBLL ...

  6. Autofac - 属性注入

    属性注入不同于通过构造函数方式传入参数. 这里是通过注入的方式, 在类创建完毕之后, 资源释放之前, 给属性赋值. 这里, 我重新弄一些类来演示这一篇吧. public class ClassA { ...

  7. Autofac - 事件

    Autofac在提供之前那些方法的时候, 同时提供了五个事件, 这一篇就看一下这几个事件. 一.五大事件 builder.RegisterType<Person>().As<IPer ...

  8. Autofac - 服务

    上一篇中, 留了一个小问题,在一个接口下面, 注册多个类, 并能正常获取. 之前的方式是不能做到的, 在服务中, 有一种实现方式是可以的. 一.服务 1. 类型 - 描述服务的基本方法 上一篇其实使用 ...

  9. Autofac - 组件

    快到年终了, 最近项目比较悠闲, 就想总结下, 项目中所使用到的一些技术, 以及使用方法. 之前有写过Dapper以及Dapper的一个扩展, 这些也是项目中使用过的. 算是一个温故而知新吧. 代码: ...

随机推荐

  1. 【Hello CC.NET】CC.NET 实现自动化集成

    一.背景 公司的某一金融项目包含 12 个子系统,新需求一般按分支来开发,测完后合并到主干发布.开发团队需要同时维护开发环境.测试环境.模拟环境(主干).目前面临最大的两个问题: 1.子系统太多,每次 ...

  2. 业务安全通用解决方案——WAF数据风控

    业务安全通用解决方案——WAF数据风控 作者:南浔@阿里云安全 “你们安全不要阻碍业务发展”.“这个安全策略降低用户体验,影响转化率”——这是甲方企业安全部门经常听到合作团队抱怨.但安全从业者加入公司 ...

  3. 【腾讯Bugly干货分享】微信mars 的高性能日志模块 xlog

    本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/581c2c46bef1702a2db3ae53 Dev Club 是一个交流移动 ...

  4. 玩转JavaScript OOP[2]——类的实现

    概述 当我们在谈论面向对象编程时,我们在谈论什么?我们首先谈论的是一些概念:对象.类.封装.继承.多态.对象和类是面向对象的基础,封装.继承和多态是面向对象编程的三大特性. JavaScript提供了 ...

  5. Web3DGame之路(三)分析babylonjs

    BabylonJS的例子十分详实 http://doc.babylonjs.com/tutorials Babylonjs的学习比较顺畅,开始做一些深入分析   一.语言选择 首先是js还是ts的问题 ...

  6. ASP.NET MVC 控制器激活(一)

    ASP.NET MVC 控制器激活(一) 前言 在路由的篇章中讲解了路由的作用,讲着讲着就到了控制器部分了,从本篇开始来讲解MVC中的控制器,控制器是怎么来的?MVC框架对它做了什么?以及前面有的篇幅 ...

  7. Android学习——uses-sdk标签详解

    1 前言 我们都知道,Android的版本在不断的迭代,并且每个版本都加入了不同的新特性.那么随着Android的用户量越来越多,Android的开发人员就必须熟悉Android各个版本的特性并且确保 ...

  8. ASP.NET MVC 从零开始 - 自动化部署(其一)

    本文是从我的 github 博客 http://lxconan.github.io 导入的. 这是这个系列的第四篇了,前三篇请参见: ASP.NET MVC 从零开始 – Create and Run ...

  9. C语言 · 图形显示

    问题描述 编写一个程序,首先输入一个整数,例如5,然后在屏幕上显示如下的图形(5表示行数): * * * * * * * * * * * * * * *     #include "stdi ...

  10. [Hadoop大数据]——Hive连接JOIN用例详解

    SQL里面通常都会用Join来连接两个表,做复杂的关联查询.比如用户表和订单表,能通过join得到某个用户购买的产品:或者某个产品被购买的人群.... Hive也支持这样的操作,而且由于Hive底层运 ...