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

posted @   dreamw  阅读(170)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2021-08-05 SourceTree使用方法(拉取、提交、推送、获取、冲突解决、分支管理)
点击右上角即可分享
微信分享提示