AutoFac学习笔记三(构造函数、属性、方法注入等问题)
第一种情况:正常通过构造函数注入
首先,我这里有两个抽象接口类(ISutdentService、IPersonService),两个具体实现的类(SutdentService、PersonService),SutdentService是ISutdentService的实现,PersonService是IPersonService的实现;PersonService需要依赖ISutdentService。就可以在PersonService中使用构造函数的方式将ISutdentService注入。
namespace AutoFac_Study.Service
{
public class PersonService : IPersonService
{
private readonly IStudentService _studentService = null;
/// <summary>
/// 通过构造函数注入IStudentService
/// </summary>
/// <param name="studentService"></param>
public PersonService(IStudentService studentService)
{
this._studentService = studentService;
}
public string GetPersonInfo()
{
return _studentService.getInfo();
}
}
}
namespace AutoFac_Study.Service
{
public class StudentService : IStudentService
{
/// <summary>
/// 具体实现
/// </summary>
/// <returns></returns>
public string getInfo()
{
string name = "张三";
string age = "18";
return $"姓名{name},年龄{age}";
}
}
}
ContainerBuilder containerBuilder = new ContainerBuilder();
//配置对应关系
containerBuilder.RegisterType<StudentService>().As<IStudentService>();
containerBuilder.RegisterType<PersonService>().As<IPersonService>();
IContainer container = containerBuilder.Build();
IPersonService personService = container.Resolve<IPersonService>();
Console.WriteLine(personService.GetPersonInfo());
第二种情况:当我们根据容器获取对象的时候,实际会执行到需要创建对象的类的构造函数中去,那么当这个类中有两个或者多个构造函数的时候,它会调用哪一个构造函数呢?
在PersonService中创建了三个构造函数,没给构造函数的参数数量均不相同,然后通过同容器得到IPersonService对象,经过调试发现,默认走的参数最多的一个构造函数。
那么问题来了,如何选择其中只有一个参数的构造函数去创建对象呢?
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<StudentService>().As<IStudentService>();
//containerBuilder.RegisterType<PersonService>()
// .UsingConstructor(typeof(IStudentService), typeof(IStudentService))//选择类型为(IStudentService,IStudentService)的构造函数
// .As<IPersonService>();
containerBuilder.RegisterType<PersonService>()
//选择类型只有一个(IStudentService)的构造函数,如果类型为别的类型,就typeof(别的类型,和构造函数保持一直即可)
.UsingConstructor(typeof(IStudentService))
.As<IPersonService>();
IContainer container = containerBuilder.Build();
IPersonService personService = container.Resolve<IPersonService>();
Console.WriteLine(personService.GetPersonInfo());
通过UsingConstructor传入指定的类型后,我们可以控制调用哪个构造函数了。
第三种情况:属性注入
如果一个类中,我们在获取这个类对象的时候,希望同时把这个类中的一些属性也进行注入改怎样实现呢?
我这里分别创建三个实体类,StudentInfo、PersonInfo、TeacherInfo。在PersonServer中定义这三个类的属性。
进行属性注册
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterInstance(new StudentInfo());
containerBuilder.RegisterInstance(new PersonInfo());
containerBuilder.RegisterInstance(new TeacherInfo());
containerBuilder.RegisterType<StudentService>().As<IStudentService>();
containerBuilder.RegisterType<PersonService>()
.As<IPersonService>()
.PropertiesAutowired();//标识支持属性注入
IContainer container = containerBuilder.Build();
IPersonService personService = container.Resolve<IPersonService>();
通过以上代码,可以对对象中的所有属性进行赋值,那么问题来了,我只想给部分属性进行赋值,该怎么操作呢?
a.首先我们需要自定义一个Attribute
namespace AutoFac_Study.Utility.AutoFacExt
{
/// <summary>
/// 创建一个自定义的Attribute
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class CusotmAutofacSelectAttribute:Attribute
{
}
}
b.接下来创建一个类来实现IPropertySelector接口中的方法
//引入命名空间
using Autofac.Core;
namespace AutoFac_Study.Utility.AutoFacExt
{
public class CustomAutofacPropertySelector : IPropertySelector
{
/// <summary>
/// 实现接口
/// </summary>
/// <param name="propertyInfo"></param>
/// <param name="instance"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool InjectProperty(PropertyInfo propertyInfo, object instance)
{
//在这里判断哪些属性是需要属性注入的
return propertyInfo.CustomAttributes.Any(c => c.AttributeType == typeof(CusotmAutofacSelectAttribute));
}
}
}
c.把一步中创建的Attribute标注在需要注入的属性中。
/// <summary>
/// 三个属性
/// </summary>
[CusotmAutofacSelectAttribute]//标注在需要注入的属性中
public PersonInfo _personInfo { get; set; }
public StudentInfo _studentInfo { get; set; }
public TeacherInfo _teacherInfo { get; set; }
d.修改PropertiesAutowired方法。
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterInstance(new StudentInfo());
containerBuilder.RegisterInstance(new PersonInfo());
containerBuilder.RegisterInstance(new TeacherInfo());
containerBuilder.RegisterType<StudentService>().As<IStudentService>();
containerBuilder.RegisterType<PersonService>()
.As<IPersonService>()
//.PropertiesAutowired();//标识支持全部属性注入
.PropertiesAutowired(new CustomAutofacPropertySelector());//只注入标记了的属性
IContainer container = containerBuilder.Build();
IPersonService personService = container.Resolve<IPersonService>();
d.接下来我们通过容器得到IPersonService对象就可以只注入_personInfo属性了。
第四种情况:方法注入,当我们通过容器得到某个对象后,需要让它自动执行某个方法,就可以使用方法注入。
首先,我们在PersonService中定义一个方法。
接下来通过容器得到对象
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterInstance(new StudentInfo());
containerBuilder.RegisterType<StudentService>().As<IStudentService>();
containerBuilder.RegisterType<PersonService>()
.As<IPersonService>()
.OnActivated(active =>
{
active.Instance.ShowInfo();//需要被执行的方法
});
IContainer container = containerBuilder.Build();
IPersonService personService = container.Resolve<IPersonService>();
————————————————
版权声明:本文为CSDN博主「淳力」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Mr_chunchun/article/details/123131546
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2021-08-05 SourceTree使用方法(拉取、提交、推送、获取、冲突解决、分支管理)