AutoFac记录
概念
Autofac是一个轻量级的依赖注入的框架,同类型的框架还有Spring.NET,Unity,Castle等;
ContainerBuilder:将组件注册成服务的创建者。
组件:Lambda表达式/一个类型/一个预编译的实例/实例类型所在的程序集
container 容器:通过 ContainerBuilder.Build()创建
获得对象:container.Resolve();
As()方法:可以指定相同的组件暴露成不同的服务。有些没有as就是将本身暴露给用户
组件注册成服务(暴露给用户)
常用注册的方式
1.通过RegisterType
2.同lambda表达式
3.通过实例来注册
4.程序集创建 RegisterAssemblyTypes
5.泛型注册 RegisterGeneric
public class 注册方式
{
/// <summary>
/// 1.RegisterType AutoFac能够通过反射检查一个类型,选择一个合适的构造函数,创造这个对象的实例
/// </summary>
[TestMethod]
public void RegisterType()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>();//方式1
builder.RegisterType(typeof(TestClass));//方式2
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 1.RegisterType Named 命名方式注册
/// </summary>
[TestMethod]
public void RegisterType2()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().Named<TestClass>("TestClass");
IContainer container = builder.Build();
// var class1 = container.Resolve<TestClass>(); error
var class2 = container.ResolveNamed<TestClass>("TestClass");
// Assert.IsTrue(class1 == null);
Assert.IsTrue(class2 != null);
} /// <summary>
/// 2.Lambda 通过反射的方式实现
/// </summary>
[TestMethod]
public void Lambda()
{
var builder = new ContainerBuilder();
builder.Register(p=>new TestClass());
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 3.RegisterInstance 实例创建
/// </summary>
[TestMethod]
public void RegisterInstance1()
{
var builder = new ContainerBuilder();
builder.RegisterInstance<TestClass>(new TestClass());
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 3.RegisterInstance 将自己系统中原有的单例注册为容器托管的单例
/// </summary>
[TestMethod]
public void RegisterInstance2()
{
var builder = new ContainerBuilder();
builder.RegisterInstance(TestClass2.GetInstance()).ExternallyOwned();
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass2>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 4.RegisterAssemblyTypes 程序集的创建
/// </summary>
[TestMethod]
public void RegisterAssemblyTypes()
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(Assembly.Load("UnitTestProject1")).Where(p => p.Name == "TestClass");
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 5.RegisterGeneric 泛型注册
/// </summary>
[TestMethod]
public void RegisterGeneric()
{
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(TestClass3<>));
IContainer container = builder.Build();
var myIntList = container.Resolve<TestClass3<int>>();
Assert.IsTrue(myIntList != null);
var myStringList = container.Resolve<TestClass3<string>>();
Assert.IsTrue(myStringList != null);
} }
注册方式扩展
1.指定构造函数
2.构造函数的参数
3.属性注入
4.方法注入
public class 注册方式扩展
{
/// <summary>
/// 构造函数注入
/// Autofac默认从容器中选择参数最多的构造函数。如果想要选择一个不同的构造函数,就需要在注册的时候就指定它。
/// *可以跟Name或者索引结合起来注册不同的构造函数
/// </summary>
[TestMethod]
public void RegisterType()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass4Paramter1>();
builder.RegisterType<TestClass4Paramter2>();
builder.RegisterType<TestClass4>().UsingConstructor(typeof(TestClass4Paramter1));
// builder.RegisterType<TestClass4>();
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass4>();
Assert.IsTrue(class1.dd == );
} /// <summary>
/// 构造函数参数 WithParameters WithParameter
/// </summary>
[TestMethod]
public void RegisterType2()
{
var builder = new ContainerBuilder();
//错误情况 多个参数
//List<NamedParameter> ListNamedParameter = new List<NamedParameter>()
//{ new NamedParameter("paramter1", "dddd")
//};
//builder.RegisterType<TestClass5>().WithParameters(ListNamedParameter); //错误
// builder.RegisterType<TestClass5>().WithParameter(new NamedParameter("paramter1", "dddd")); //错误
// List<ResolvedParameter> ListNamedParameter = new List<ResolvedParameter>()
// { new ResolvedParameter(
//(pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "paramter1",
//(pi, ctx) => "sectionName") // };
// builder.RegisterType<TestClass5>().WithParameters(ListNamedParameter); //正确情况
//builder.RegisterType<TestClass5>().WithParameter("paramter1", "sectionName"); IContainer container = builder.Build();
var class1 = container.Resolve<TestClass5>();
Assert.IsTrue(class1.dd == );
} /// <summary>
///属性注入
/// </summary>
[TestMethod]
public void RegisterType3()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass6>().WithProperty("dd", );
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass6>();
Assert.IsTrue(class1.dd == );
} /// <summary>
///方法注入 指定注入的方法
/// </summary>
[TestMethod]
public void RegisterType4()
{
var builder = new ContainerBuilder();
builder.Register(c =>
{
var result = new TestClass7();
result.SetDependency(c.Resolve<ITestClass7>());
return result;
});
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass7>();
Assert.IsTrue(class1 != null);
} /// <summary>
///方法注入 使用Activating Handler 指定自身注册完成后触发的事件
/// </summary>
[TestMethod]
public void RegisterType5()
{
var builder = new ContainerBuilder();
builder.Register<TestClass8>(c => new TestClass8()).OnActivating(e => e.Instance.SetDependency(new TestClass6()));
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass8>();
Assert.IsTrue(class1 != null);
} } public class TestClass4
{
public int dd = ; public TestClass4(TestClass4Paramter1 a)
{
dd = ;
} public TestClass4(TestClass4Paramter2 a)
{
dd = ;
} public TestClass4(TestClass4Paramter1 a, TestClass4Paramter2 b)
{
dd = ;
} } public class TestClass4Paramter1
{ } public class TestClass4Paramter2
{ } public class TestClass5
{
public int dd = ;
public TestClass5(string a)
{
dd = ;
} } public class TestClass6
{ public int dd { get; set; }
} public class TestClass7
{
private ITestClass7 ITestClass7;
public void SetDependency(ITestClass7 ITestClass7)
{
this.ITestClass7 = ITestClass7;
}
} public interface ITestClass7
{ } public class TestClass8
{ public void SetDependency(TestClass6 ITestClass6)
{
var t = ITestClass6.dd;
}
}
获取服务
常用的获取服务的方式
public class 获取服务
{
/// <summary>
/// Resolve
/// </summary>
[TestMethod]
public void Resolve()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>();
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// ResolveNamed
/// </summary>
[TestMethod]
public void ResolveNamed()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().Named<TestClass>("TestClass");
IContainer container = builder.Build();
var class2 = container.ResolveNamed<TestClass>("TestClass");
Assert.IsTrue(class2 != null);
} /// <summary>
/// ResolveKeyed 有Name的方式很方便,但是只支持字符串,但有时候我们可能需要通过其他类型作键。
/// </summary>
[TestMethod]
public void ResolveKeyed()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().Keyed<TestClass>(TestState.服务1);
IContainer container = builder.Build();
var class2 = container.ResolveKeyed<TestClass>(TestState.服务1);
Assert.IsTrue(class2 != null);
} [TestMethod]
public void ResolveIIndex()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().Keyed<TestClass>(TestState.服务1);
IContainer container = builder.Build();
IIndex<TestState, TestClass> IIndex = container.Resolve<IIndex<TestState, TestClass>>();
TestClass p = IIndex[TestState.服务1];
Assert.IsTrue(p != null);
}
}
获取服务扩展
当注册或者检索component的时候可以使用参数。
1、传递参数给Resolve
Resolve接受可变参数或IEnumerable<T>传入多个值
using (IContainer container = builder.Build())
{
AutoFacManager manager = container.Resolve<AutoFacManager>(new NamedParameter("name", "刘备"));
Console.WriteLine(manager.Name); //输出 刘备
manager.Say();
}
此时,AutoFacManager下必须添加如下构造函数
public AutoFacManager(string name,IPerson MyPerson)
{
Name = name;
person = MyPerson;
}
2、可用的参数类型
Autofac提供几种不同的参数对应策略:
- NamedParameter :像上面那样对应的参数名字
- TypedParameter:对应到参数的类型(必须是具体的类型)
- ResolvedParameter:灵活的参数匹配
- NamedParameter 和TypedParameter:只能提供常量参数
3、从表达式中使用参数
如果使用表达式注册的方式,可以使用第二个可用的委托参数来获得参数。
builder.Register((c, p) => new AutoFacManager(p.Named<string>("name"), c.Resolve<IPerson>()));
builder.RegisterType<Worker>().As<IPerson>();
using (IContainer container = builder.Build())
{
AutoFacManager manager = container.Resolve<AutoFacManager>(new NamedParameter("name", "刘备"));
Console.WriteLine(manager.Name); //输出刘备
manager.Say();
}
特殊问题
循环依赖
生命周期
生命周期不同阶段使用的事件
主要用于处理一些依赖关系比如在初始化该类之前某个类必须初始化好
或者当前类初始化后其他相关的类必须进行初始化 目前比较不常用
Autofac暴露五个事件接口供实例的按如下顺序调用
- OnRegistered
- OnPreparing
- OnActivated
- OnActivating
- OnRelease
builder.RegisterType<Worker>().As<IPerson>()
.OnRegistered(e => Console.WriteLine("在注册的时候调用!"))
.OnPreparing(e => Console.WriteLine("在准备创建的时候调用!"))
.OnActivating(e => Console.WriteLine("在创建之前调用!"))
.OnActivated(e => Console.WriteLine("创建之后调用!"))
.OnRelease(e => Console.WriteLine("在释放占用的资源之前调用!"));
默认有三种生命周期:
1.Per Dependency:默认的生命周期 每次请求都创建一个新的对象
2.Single Instance:单例模式 每次都用同一个对象
3.Per Lifetime Scope:同一个生命周期生成的对象是同一个实例
public class 生命周期
{
/// <summary>
/// 默认生命周期
/// </summary>
[TestMethod]
public void PerDependency()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().InstancePerDependency();
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
var class2 = container.Resolve<TestClass>();
Assert.IsFalse(object.ReferenceEquals(class1, class2));
} /// <summary>
/// 单例 每次都用同一个对象(不同用户使用相同的第一次实例)
/// </summary>
[TestMethod]
public void SingleInstance()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().SingleInstance(); IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
var class2 = container.Resolve<TestClass>();
Assert.IsTrue(object.ReferenceEquals(class1, class2));
} /// <summary>
/// 同一生命周期内使用同一个对象
/// </summary>
[TestMethod]
public void PerLifetimeScope()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().InstancePerLifetimeScope(); IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
var class2 = container.Resolve<TestClass>(); ILifetimeScope inner = container.BeginLifetimeScope();
var class3 = inner.Resolve<TestClass>();
var class4 = inner.Resolve<TestClass>(); Assert.IsTrue(object.ReferenceEquals(class1, class2));
Assert.IsFalse(object.ReferenceEquals(class1, class3));
Assert.IsTrue(object.ReferenceEquals(class3, class4));
} }
config配置注入
static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<AutoFacManager>();
builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
using (IContainer container = builder.Build())
{
AutoFacManager manager = container.Resolve<AutoFacManager>();
manager.Say();
} Console.ReadKey();
}
AutoFac在MVC中的应用
参考资料:http://docs.autofac.org/en/latest/
AutoFac记录的更多相关文章
- 记录对依赖注入的小小理解和autofac的简单封装
首先,我不是一个开发者,只是业余学习者.其次我的文化水平很低,写这个主要是记录一下当前对于这块的理解,因为对于一个低水平 的业余学习者来说,忘记是很平常的事,因为接触.应用的少,现在理解,可能过段时间 ...
- 个人项目框架搭建 -- Autofac简单使用记录
1.添加autofac相关程序集/使用Nuget 2.引入命名空间 using Autofac; using Autofac.Configuration; 3.使用 3.1:直接使用 var buil ...
- autofac 学习记录
builder.RegisterModule(new ConfigurationSettingsReader()); 需要注册上面一句才能读到.config里的节点,xml配置方式如下 <con ...
- 2_MVC+EF+Autofac(dbfirst)轻型项目框架_用户权限验证
前言 接上面两篇 0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架 与 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例) .在第一篇中介 ...
- 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例)
前言 在上一篇0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架中,我已经介绍了这个轻型框架的层次结构,在下面的这篇文章中,我将以教师登陆功能为例,具体来扩充下我的core层的代 ...
- .NET 4.5+项目迁移.NET Core的问题记录
.NET 4.5+项目迁移.NET Core的问题记录 这几天试着把目前的开发框架迁移到新的.net core平台,中间遇到的问题在这里简单记录一下. 迁移过程遇到的最大的问题IOC容器.我目前使用的 ...
- Autofac Container 的简单的封装重构
为了使用方便,对Autofac container的简单封装,记录如下,备以后用或分享给大家,欢迎讨论! using Autofac; using Autofac.Core.Lifetime; usi ...
- Ioc容器Autofac系列(1)-- 初窥
一.前言 第一次接触Autofac是因为CMS系统--Orchard,后来在一个开源爬虫系统--NCrawler中也碰到过,随着深入了解,我越发觉得Ioc容器是Web开发中必不可少的利器.那么,Io ...
- Ioc Autofac心得
对于这个容器注入,个人也不是很熟悉,很多还不懂,只会基本的操作,几天把它记录下来,说不定以后帮助就大了呢,这方面跟安卓差距还是挺大的 下面记录下应用的流程 步骤: 1.添加应用 2.重写工厂(这里讲的 ...
随机推荐
- anaconda3/lib/libcrypto.so.1.0.0: no version information available (required by wget)
Solution: sudo ldconfig /lib/x86_64-linux-gnu/ #you need to use the libcrypto.so from /lib/x86_64-li ...
- ds18b20采集温度并上报服务器
交叉编译器:arm-linux-gcc-4.5.4 Linux内核版本:Linux-3.0 主机操作系统:Centos 6.5 开发板:FL2440 温度传感器:ds18b20 注:此程序的客户端是在 ...
- Wordpress无法连接Mysql8的问题
安装了mysql 8.0.11 之后本地可以登录,但是远程第三方工具无法连接,本地安装的Wordpress在初始化时也连接失败.防火墙已经放通的, 解决之道: 首先登陆到mysql命令行: mysql ...
- 如何获取ubuntu源码包里面的源码?
ubuntu 源仓库说明 1.在获取源码包之前,确保在软件源配置文件/etc/apt/sources.list中添加了deb-src项 vim /etc/apt/sources.list # # de ...
- Warning: Function created with compilation errors.
SQL> create or replace function 2 remove_constants(p_query in varchar2) return varchar2 3 as 4 l_ ...
- node.js中的框架
node.js中的框架 载自: http://nodeframework.com/ MVC frameworks Sinatra-like These frameworks offer rich co ...
- SNFAutoupdater通用自动升级组件V2.0
1.组件介绍 C/S构的特点是能充分发挥客户端的处理能力,很多工作可以由客户端处理后再提交给服务器,对应的优点就是客户端响应速度快模式客户端以其强大的功能,丰富的表现力受到相当大部分用户的青睐,但是客 ...
- 基于vue-cli项目添加服务端渲染
两个示例的git地址: 1. 我的环境 2. 方式一:使用prerender-spa-plugin插件获得SSR的效果. 2.1 说明 2.2 初始化 1 vue init webpack vue-p ...
- JS 日期转换,格式化等常用的函数定义
//判断字符串是否日期格式 function isDate(val) { return new Date(val) != "Invalid Date"; } //日期格式化 fun ...
- 项目在iOS11上遇到的小问题
iOS11正式版出了这么久了,在忙完新版本开发,写下在iOS11上的一些小问题. 1 App图标不显示 现象:升级到iOS11系统下自己的项目桌面app图标不见了 出现这种情况我还以为自己手动删除 ...