第四十一节:再探依赖注入(coreMvc/应用启动/控制台)和多项目框架集成(原生反射、AutoFac集成新写法)
一. 再探依赖注入
其它详细用法参考之前的博客:https://www.cnblogs.com/yaopengfei/p/10754397.html
https://www.cnblogs.com/yaopengfei/p/12664400.html
官网:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-6.0
1. coreMvc中注入
直接在Program中注入即可, 可以以接口的形式注入,也可以直接注入类
//1. 普通注入
builder.Services.AddScoped<IUserInfo, UserInfo>();
builder.Services.AddScoped<RoleInfo>();
使用的时候在控制器中通过构造函数注入即可,代码略。
2. 在应用启动中解析
(即在program中要使用,这里是解析使用,注册使用的还是1中的注册)
(1). 通过 var serviceScope = app.Services.CreateScope()
(2). 通过GetRequiredService方法进行对象的解析
var app = builder.Build();
//2.在应用启动中解析使用(使用的还是1中的普通注入)
using (var serviceScope = app.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
var userInfo = services.GetRequiredService<IUserInfo>();
var roleInfo = services.GetRequiredService<RoleInfo>();
Console.WriteLine("------------------测试在应用启动中解析使用------------------------------");
Console.WriteLine(userInfo.GetInfo());
Console.WriteLine(roleInfo.GetInfo());
}
3.直接在控制台中使用
直接注册+解析
需要依赖【 Microsoft.Extensions.DependencyInjection】程序集,详见下面代码
//3. 测试控制台中使用
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<IUserInfo, UserInfo>();
var serviceProvider = serviceCollection.BuildServiceProvider();
IUserInfo userService = serviceProvider.GetRequiredService<IUserInfo>();
//下面是使用
var result = userService.GetInfo();
}
二. 多项目框架集成
1. 需求
有多个项目, Ypf.Service、Ypf.IService、03-CoreMvcDI三个项目, 其中CoreMvcDI添加对Ypf.IService的引用,然后把Ypf.Service项目的输出路径改为 【..\03-CoreMvcDI\bin\】
想把Ypf.Service中所有实现ISupport接口的类注册个他的实现接口
[FromServices] IInfo2 _info2 是注册失败的,因为没有实现ISupport接口 (需要加上以后再测试一下哦)
特别注意:这里的输出路径改为 Ypf.Service项目的输出路径改为 【..\03-CoreMvcDI\bin\】,利用合并文件夹的原则实现!!! 因为Ypf.Service项目也会生成一个Debuger文件夹
2. 原生反射写法
(和之前Core5.0中的写法基本一致)
(1). 拼接dll的路径,通过反射进行加载
(2). 获取该dll中的符合条件的类(A.去掉抽象类 B.该类要实现ISupport接口)
(3). 遍历类
A. 拿到该类的所有接口(去掉ISupport接口)
B. 遍历接口,把该类注册给所有实现的接口
代码分享:
{
var dirName = "03-Ypf.Service.dll";
Assembly asmService = Assembly.LoadFile(AppContext.BaseDirectory + dirName);
//抽象类不进行注入,没有实现ISupport接口的类不进行注入
var classList = asmService.GetTypes().Where(t => !t.GetTypeInfo().IsAbstract && typeof(ISupport).IsAssignableFrom(t)).ToList();
foreach (Type serviceType in classList)
{
//把一个类注册给它实现的全部接口(除了ISupport接口外)
var interfaceTypes = serviceType.GetInterfaces().Where(t => t.Name != "ISupport").ToList();
foreach (var interfaceType in interfaceTypes)
{
builder.Services.AddScoped(interfaceType, serviceType);
}
}
}
3. AutoFac集成新写法
和之前Core5.0的写法有区别,详见Program中的代码
public class MyAutoFacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
{
//这里就是AutoFac的注入方式,下面采用常规的方式
//详见:https://www.cnblogs.com/yaopengfei/p/9479268.html
//官网:https://autofac.org/
//特别注意:其中很大的一个变化在于,Autofac 原来的一个生命周期InstancePerRequest,将不再有效。正如我们前面所说的,整个request的生命周期被ASP.NET Core管理了,
//所以Autofac的这个将不再有效。我们可以使用 InstancePerLifetimeScope ,同样是有用的,对应了我们ASP.NET Core DI 里面的Scoped。
//在普通类中配置文件的读取麻烦,后面封装(注:appsettings.json要改为始终复制)
var Configuration = new ConfigurationBuilder().AddJsonFile(AppContext.BaseDirectory + "appsettings.json").Build();
var dirName = Configuration["IocDll"];
Assembly asmService = Assembly.LoadFile(AppContext.BaseDirectory + dirName);
builder.RegisterAssemblyTypes(asmService)
.Where(t => !t.IsAbstract && typeof(ISupport).IsAssignableFrom(t)) //只有实现了ISupport接口的类才进行注册
.AsImplementedInterfaces() //把一个类注册给它实现的全部接口
.InstancePerLifetimeScope() //作用域单例(比如Task.Run就是另外一个作用域),而非请求内单例(请求内单例用:InstancePerRequest)
.PropertiesAutowired(); //在core里表示在注入类中实现构造函数注入
}
}
}
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
// Register services directly with Autofac here. Don't call builder.Populate(), that happens in AutofacServiceProviderFactory.
builder.Host.ConfigureContainer<ContainerBuilder>(builder => builder.RegisterModule(new MyAutoFacModule()));
三. 老杨的开源框架
https://github.com/yangzhongke/NETBookMaterials/tree/main/%E6%9C%80%E5%90%8E%E5%A4%A7%E9%A1%B9%E7%9B%AE%E4%BB%A3%E7%A0%81/YouZack-VNext/Zack.Commons
主要分析RunModuleInitializers方法和ReflectionHelper.cs
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。