概念

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提供几种不同的参数对应策略:

  1. NamedParameter :像上面那样对应的参数名字
  2. TypedParameter:对应到参数的类型(必须是具体的类型)
  3. ResolvedParameter:灵活的参数匹配
  4. NamedParameter 和TypedParameter:只能提供常量参数

  3、从表达式中使用参数

  如果使用表达式注册的方式,可以使用第二个可用的委托参数来获得参数。

AutoFac记录-LMLPHP
    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暴露五个事件接口供实例的按如下顺序调用

  1. OnRegistered
  2. OnPreparing
  3. OnActivated
  4. OnActivating
  5. 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/

05-18 08:07