1、使用Assembly.Load加载程序集
//反射注入DI
var path = AppDomain.CurrentDomain.BaseDirectory;
var asses = new List<Assembly>();
var files = Directory.GetFiles(path, "*.dll");
for (int i = 0; i < files.Length; i++)
{
asses.Add(Assembly.Load(File.ReadAllBytes(files[i])));
}
2、循环遍历类,发现符合条件的类使用AddScoped方法注入DI,举例类名为LoginContext
for (int i = 0; i < asses.Count; i++)
{
var modules = asses[i].GetModules();
for (int j = 0; j < modules.Length; j++)
{
var types = modules[j].GetTypes();
for (int m = 0; m < types.Length; m++)
{
var service = types[m];
if (可注入条件)
{
services.AddScoped(service);//项目不可正常启动
services.AddScoped(typeof(LoginContext));//项目正常启动
services.AddScoped<LoginContext>();//项目正常启动
}
}
}
}
3、services内容
4、使用构造函数注入的方式
5、错误信息
只保留services.AddScoped(service);启动项目时会报错:
Unable to resolve service for type
不知道错误原因是什么,services.AddScoped()和services.AddScoped<T>()的注入效果不应该是一样的吗?
补充问题:
错误:Unable to resolve service for type 'Adam.Application.IService.System.IDemoClass'
1、准备一个测试接口类:IDemoClass和测试实现类:DemoClass
2、IDemoClass与DemoClass在同一个项目中(编译后则在同一个程序集dll),无论其命名空间是否相同
//第一种写法报错
var inj = service.GetInterface("I" + service.Name);
services.AddScoped(inj, service);
//第二种写法不报错
services.AddScoped(typeof(IDemoClass), typeof(DemoClass));
//第三种写法不报错
services.AddScoped<IDemoClass, DemoClass>();
3、IDemoClass与DemoClass不在同一个的项目中(编译后则不在同一个程序集dll),无论其命名空间是否相同
//第一种写法不会报错
var inj = service.GetInterface("I" + service.Name);
services.AddScoped(inj, service);
//第二种写法不报错
services.AddScoped(typeof(IDemoClass), typeof(DemoClass));
//第三种写法不报错
services.AddScoped<IDemoClass, DemoClass>();
疑惑点:
现在疑惑点转移到第一种写法与第二种写法的问题,为什么会造成这种限制,是我电脑环境(core5.0)的问题,还是代码本身带的这种限制,还是说写法错误
需要第一种写法的原因:
1、我在代码设计中有些注册到DI的类没有接口类
2、我是通过反射的方式将想要注册的类注册到DI中,不想写太多的注册代码
大神:
LoginContext是我自己定义的类,在设计上没打算给它设计接口类
后面我自己测试了下,使用services.AddScoped(接口类类型,实现类类型);这种注入有些限制,我不知道是不是我开发环境的问题
1、只要接口类和实现类在同一个项目(同一个dll)中,同样会报Unable to resolve service for type这个错误
2、接口类和实现类不在同一个项目中,则能正常使用
3、services.AddScoped(typeof(接口类),typeof(实现类));services.AddScoped<接口类,实现类>();这两种写法则能忽视这个限制
我想知道造成这个限制的根源,我反编译5.0版本的程序集Microsoft.Extensions.DependencyInjection.Abstractions.dll,没发现什么问题,是dotnet自己限制、还是我没能发现问题
用这个是可以的,不可以反射程序集
你先硬编码测试一下.
我测试了下,我准备了一个类DemoClass
你的意思是在controller中使用HttpContext.RequestServices获取这个serviceProvider,然后手动获取吗
1、使用services.AddScoped(service);注册到DI
var serviceProvider = HttpContext.RequestServices;
var demo = serviceProvider.GetService(typeof(DemoClass));
var demo1 = serviceProvider.GetService<DemoClass>();
demo和demo1这两个变量为null
2、使用services.AddScoped(typeof(DemoClass));注册到DI
var serviceProvider = HttpContext.RequestServices;
var demo = serviceProvider.GetService(typeof(DemoClass));
var demo1 = serviceProvider.GetService<DemoClass>();
demo和demo1这两个变量则能成功获取
是否是我因为使用Assembly.Load加载程序集的原因吗?
@愉悦的绅士:
使用的方法不对, 试试看这样: serviceProvider.getservice(service)// 这里的service和你在注入DI的是同一个type对象, 就是这个 var service = types[m];.
你分析的对
@czd890:
没怎么看明白
serviceProvider.getservice(service)
这就话是让我在项目启动注册DI容器的时候使用,还是说,在要使用该 类实例 的时候用此方法从DI容器中获取该实例?
@愉悦的绅士:
//伪代码
var serviceTypeForLoadAss = types.firstdefault(t=>t.name=="LoginContext"); //types assembly.load 来的.
var servieeType=typeof(LoginContext);
console.writeline(servieeType==serviceTypeForLoadAss) // output false.
这样子懂了不
@czd890:
懂了
比较结果为false