组件,是数据与方法的封装。也就是对象,所以除去标题外,其他地方用对象代替组件。
使用AutoFac,分为两步,注册对象与创建对象,即放进来与拿出去。
注册对象,分为三步
- 创建容器
var builder = new ContainerBuilder();
- 注册对象
builder.xxxxxx
这一节,探究AutoFac提供注册对象的各种方式- 容器闭合
var container = builder.Build();
构造注入
单独注册
按类型注册
公开注册类型
//按类型注册,公开该类型
builder.RegisterType<Person>();
//使用类型解析
var person = container.Resolve<Person>();
公开接口
//按类型注册,使用As公开接口
builder.RegisterType<Person>().As<IPerson>();
//使用接口解析
var person = container.Resolve<IPerson>();
公开注册类型与接口
//按类型注册,使用AsSelf公开类型,用As公开接口
builder.RegisterType<Person>().AsSelf().As<IPerson>();
//可以使用类型/接口解析
var person1 = container.Resolve<Person>();
var person2 = container.Resolve<IPerson>();
公开多个接口
//按类型注册,用As公开接口
builder.RegisterType<Person>().As<IPerson>().As<IPeople>();
//可以使用多种接口解析
var person = container.Resolve<IPerson>();
var people= container.Resolve<IPeople>();
按实例注册
注册普通对象
builder.RegisterInstance(new Student());
var student = new Student();
builder.RegisterInstance(student);
builder.Register(c => new Student());
按实例注册后,实例的生命周期由AutoFac处理,如果想要自己来处理
builder.RegisterInstance(new Student()).ExternallyOwned();
注册单例对象,同样,单例的对象也是实例对象的一种
builder.RegisterInstance(Worker.CreateInstance());
builder.RegisterInstance(Worker.CreateInstance()).ExternallyOwned();
批量注册
按程序集注册
当前程序集中,非静态的公开类型被批量注册
var dataAccess = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(dataAccess);
var worker= container.Resolve<Worker>();
var manager = container.Resolve<Manager>();
引用的相关程序集,也可以批量注册非静态的公开类型
var assembly = typeof(User).Assembly;
builder.RegisterAssemblyTypes(assembly);
//User与Fire在引用的其他工程中
var user = container.Resolve<User>();
var fire = container.Resolve<Fire>();
批量注册并批量公开相应的接口
var assembly = typeof(User).Assembly;
//AsImplementedInterfaces很方便的将注册类型公开为各自继承的接口
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces();
//User继承IEntities,Fire继承IModel
var user = container.Resolve<IEntities>();
var fire = container.Resolve<IModel>();
根据程序集的属性,使用Where过滤要注册的类型
var dataAccess = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(dataAccess).Where(t => t.Name.EndsWith("er"));
//student创建失败,因为对象的类型名称不少以er结尾
var worker= container.Resolve<Worker>();
var manager = container.Resolve<Manager>();
var student = container.Resolve<Student>();
根据程序集的属性,使用Except过滤要注册的类型
var dataAccess = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(dataAccess).Except<Worker>();
//worker创建失败,因为没有注册
var manager = container.Resolve<Manager>();
var student = container.Resolve<Student>();
var worker= container.Resolve<Worker>();
按模块注册
var builder = new ContainerBuilder();
builder.RegisterModule<UserModule>();
//1.调用UserModule类型中的Load方法
var container = builder.Build();
namespace Entities
{
//Module是AutoFac提供的实现IModule的类型
public class UserModule : Module
{
protected override void Load(ContainerBuilder builder)
{
//2.注册User等类型
builder.RegisterType<User>();
builder.RegisterType<Student>();
}
}
}
//3.创建User对象
User user = container.Resolve<User>();
程序集中的模块
//获取UserModule所在程序集
var assembly = typeof(UserModule).Assembly;
var builder = new ContainerBuilder();
builder.RegisterAssemblyModules<UserModule>(assembly);
//调用UserModule所在程序集中所有实现IModule的类型的Load
var container = builder.Build();
默认注册
注册顺序
多个组件公开相同的服务,AutoFac将使用最后一个注册的组件
builder.RegisterType<Person>().AS<IPerson>();
builder.RegisterType<Student>().As<IPerson>();
//解析IPerson得到的是Student对象
使用PreserveExistingDefaults选择默认注册
builder.RegisterType<Person>().AS<IPerson>().PreserveExistingDefaults();
builder.RegisterType<Student>().As<IPerson>();
//解析IPerson得到的是Person对象
解析构造
容器在解析时,默认寻找到参数最多的构造函数
//Person类型重载3个构造
public Person(){}
public Person(Book book){}
public Person(Book book, Bag bag){}
//创建Person对象时,执行的构造根据注册情况而定
var person = container.Resolve<Person>();
情景1
builder.RegisterType<Bag>();
builder.RegisterType<Book>();
builder.RegisterType<Person>();
public Person(Book book, Bag bag){}
情景2
builder.RegisterType<Book>();
builder.RegisterType<Person>();
public Person(Book book){}
情景3
设置执行仅有Book类型参数的构造
builder.RegisterType<Person>().UsingConstructor(typeof(Book));
设置执行没有参数的构造
builder.RegisterType<Person>().UsingConstructor();
构造参数
internal class Worker : IPerson
{
public Worker(string name)
{
Console.WriteLine(name);
}
}
在注册时确定参数
var builder = new ContainerBuilder();
// 方式1 按名称匹配
builder.RegisterType<Worker>().As<IPerson>().WithParameter("name", "eden");
//方式2 按类型匹配
builder.RegisterType<Worker>().As<IPerson>().WithParameter(new TypedParameter(typeof(string), "eden"));
//方式3 Lambda
builder.RegisterType<Worker>().As<IPerson>().WithParameter(
new ResolvedParameter((pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "name", (pi, ctx) => "pp"));
var container = builder.Build();
在解析时确定参数
var builder = new ContainerBuilder();
builder.Register((c, p) =>new Worker(p.Named<string>("name"))).As<IPerson>();
var container = builder.Build();
var obj = container.Resolve<IPerson>(new NamedParameter("name", "pp"));
初始化属性
用Lambda可以初始化属性,c在这里代表注册的上下文IComponentContext
builder.Register(c=> new Student(){ Name = "eden", BookObj = new Book()});
c.ResolveOptional<Book>()意味着从注册的中寻找Book对象反射创建来填充BookObj属性
builder.RegisterType<Book>();
builder.Register(c=> new Student(){ Name = "eden", BookObj = c.ResolveOptional<Book>()});
选择注册
参数化
var builder = new ContainerBuilder();
builder.Register<IPerson>(
(c, p) =>
{
var id = p.Named<int>("id");
if (1 == id)
{
return new Student();
}
else //细节
{
return new Worker();
}
});
var container = builder.Build();
var obj = container.Resolve<IPerson>(new NamedParameter("id", 1));
在解析时,传入一个临时的参数key-value(id = 1),容器根据参数进行逻辑处理,决定选择哪个对象实例化创建
细节:这里必须return一个对象,由else改为else if无法通过编译
条件化
如果没有注册A才注册B
var builder = new ContainerBuilder();
//②在这里注册了Worker类型并暴露为IPerson类型
builder.RegisterType<Worker>().As<IPerson>();
//③如果没有暴露的IPerson类型,注册Student类型
builder.RegisterType<Student>().As<IPerson>().IfNotRegistered(typeof(IPerson));
var container = builder.Build();
//解析为Worker类型
var obj = container.Resolve<IPerson>();
var builder = new ContainerBuilder();
//②如果没有暴露的IPerson类型,注册Student类型
builder.RegisterType<Student>().As<IPerson>().IfNotRegistered(typeof(IPerson));
var container = builder.Build();
//解析为Student类型
var obj = container.Resolve<IPerson>();
如果注册了A才注册B
var builder = new ContainerBuilder();
//② 注册了Worker类型,并暴露为IPerson类型
builder.RegisterType<Worker>().As<IPerson>();
//③ 如果有暴露的IPerson类型,才注册Manager类型,并暴露为IManager类型
builder.RegisterType<Manager>().As<IManager>().OnlyIf(reg=>reg.IsRegistered(new TypedService(typeof(IPerson))));
var container = builder.Build();
var obj= container.Resolve<IManager>();
var builder = new ContainerBuilder();
//② 如果有暴露的IPerson类型,才注册Manager类型,并暴露为IManager类型
builder.RegisterType<Manager>().As<IManager>().OnlyIf(reg=>reg.IsRegistered(new TypedService(typeof(IPerson))));
var container = builder.Build();
//编译通过,运行出错
var obj= container.Resolve<IManager>();
泛型注册
internal interface IRepository<T>
{
void Add(T item);
}
internal class EntityFrameworkRepository<T> : IRepository<T>
{
public void Add(T item)
{
Console.WriteLine(item);
}
}
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(EntityFrameworkRepository<>)).As(typeof(IRepository<>));
var container = builder.Build();
var workerRepository = container.Resolve<IRepository<Worker>>();
workerRepository.Add(new Worker());
var studentRepository= container.Resolve<IRepository<Student>>();
studentRepository.Add(new Student());
属性注入
internal class Worker : People, IPerson
{
public Student Student { get; set; }
public string Name { get; set; }
public Worker(string name)
{
Console.WriteLine(name);
}
}
Lambda + 对象初始化器
var builder = new ContainerBuilder();
builder.Register(c=> new Worker {Name = "eden"});
var container = builder.Build();
var obj = container.Resolve<Worker>();
名称匹配
var builder = new ContainerBuilder();
builder.RegisterType<Worker>().WithProperty("Name", "eden");
var container = builder.Build();
var obj = container.Resolve<Worker>();
反射组件
var builder = new ContainerBuilder();
//student使用已注册
builder.RegisterType<Student>();
//PropertiesAutowired将在解析创建Worker对象时自动创建属性的Student对象
builder.RegisterType<Worker>().PropertiesAutowired();
var container = builder.Build();
//obj.Student != null
var obj = container.Resolve<Worker>();
注入循环依赖
public class ClassA
{
private readonly ClassB _b;
public ClassA(ClassB b)
{
_b = b;
}
}
public class ClassB
{
public ClassA ClassA { get; set; }
}
ClassA与ClassB已经造成循环依赖
var builder = new ContainerBuilder();
builder.Register(c => new ClassA(new ClassB()));
builder.Register(c => new ClassB()).OnActivated(e => e.Instance.ClassA = e.Context.Resolve<ClassA>());
var container = builder.Build();
var obj = container.Resolve<ClassB>();
方法注入
internal class Worker : People, IPerson
{
private Student _student;
private string _name;
public void SetName(string name)
{
_name = name;
}
public void SetStudent(Student student)
{
_student = student;
}
}
方式1
var name = "eden";
var builder = new ContainerBuilder();
builder.Register(c =>
{
var worker = new Worker();
worker.SetName(name);
return worker;
});
var container = builder.Build();
var obj = container.Resolve<Worker>();
方式2
var name = "eden";
var builder = new ContainerBuilder();
builder.RegisterType<Student>();
builder.RegisterType<Worker>()
.OnActivating(e =>
{
var stu = e.Context.Resolve<Student>();
e.Instance.SetStudent(stu);
});
var container = builder.Build();
var obj = container.Resolve<Worker>();
后记
花费了将近2个星期内的空余时间,看官网中组件注册这一章,按照自己的逻辑归纳出这篇博客。使用程序集注册+自动公开接口的方式,将Services模块注册,一行代码干掉了140行。