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