基于配置文件的依赖解析:Asp.Net Core下Unity DI适配问询
从Unity配置迁移到ASP.NET Core配置文件驱动的依赖注入
嘿,我之前刚好折腾过从Unity DI转ASP.NET Core的配置化依赖注入,给你分享两种靠谱的思路,看你需求选:
思路一:完全迁移到ASP.NET Core原生DI(推荐)
ASP.NET Core原生DI本身默认不直接支持Unity那种XML配置,但我们可以用配置文件(JSON/XML)定义服务映射,再通过反射自动注册到原生容器里,步骤很清晰:
1. 准备配置文件(JSON为例,更主流)
把你原来的Unity XML配置转换成JSON格式,在appsettings.json里新增一个ServiceMappings节点:
{ "ServiceMappings": [ { "InterfaceType": "MyLibrary.Interfaces.IDepartmentManager, MyLibrary", "ImplementationType": "MyLibrary.DepartmentManager, MyLibrary", "Lifecycle": "Scoped" // 可选:Transient/Scoped/Singleton,对应原生DI的生命周期 }, { "InterfaceType": "MyLibrary.Interfaces.IFtpFileSender, MyLibrary", "ImplementationType": "MyLibrary.FtpFileSender, MyLibrary", "Lifecycle": "Transient" } ] }
2. 创建配置绑定模型
新建一个类来映射配置里的每个服务条目:
public class ServiceMapping { public string InterfaceType { get; set; } public string ImplementationType { get; set; } public string Lifecycle { get; set; } = "Scoped"; // 默认生命周期 }
3. 在Program.cs里读取配置并注册服务
在启动代码里加载配置,反射解析类型,然后注册到DI容器:
var builder = WebApplication.CreateBuilder(args); // 从appsettings.json读取服务映射配置 var serviceMappings = builder.Configuration .GetSection("ServiceMappings") .Get<List<ServiceMapping>>(); foreach (var mapping in serviceMappings) { // 解析接口和实现类的Type对象 var interfaceType = Type.GetType(mapping.InterfaceType); var implementationType = Type.GetType(mapping.ImplementationType); if (interfaceType == null || implementationType == null) { // 可以加日志记录找不到类型的情况 continue; } // 根据配置的生命周期注册服务 switch (mapping.Lifecycle.ToLower()) { case "transient": builder.Services.AddTransient(interfaceType, implementationType); break; case "singleton": builder.Services.AddSingleton(interfaceType, implementationType); break; default: // 默认Scoped builder.Services.AddScoped(interfaceType, implementationType); break; } } // 其他WebAPI配置(比如添加控制器等) builder.Services.AddControllers(); var app = builder.Build(); // 中间件配置... app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
可选:用XML配置代替JSON
如果你想尽量贴近原来的Unity XML格式,也可以用XML配置:
- 新建
services.xml文件:
<ServiceMappings> <ServiceMapping> <InterfaceType>MyLibrary.Interfaces.IDepartmentManager, MyLibrary</InterfaceType> <ImplementationType>MyLibrary.DepartmentManager, MyLibrary</ImplementationType> <Lifecycle>Scoped</Lifecycle> </ServiceMapping> <ServiceMapping> <InterfaceType>MyLibrary.Interfaces.IFtpFileSender, MyLibrary</InterfaceType> <ImplementationType>MyLibrary.FtpFileSender, MyLibrary</ImplementationType> <Lifecycle>Transient</Lifecycle> </ServiceMapping> </ServiceMappings>
- 在Program.cs里加载XML配置:
builder.Configuration.AddXmlFile("services.xml", optional: false, reloadOnChange: true);
之后的绑定和注册逻辑和JSON版本完全一致,不用改模型类和循环代码。
思路二:继续使用Unity容器(兼容原有配置)
如果你不想改原来的Unity XML配置,也可以把Unity集成到ASP.NET Core里,步骤如下:
1. 安装Unity集成包
在NuGet上安装Unity.Microsoft.DependencyInjection包:
Install-Package Unity.Microsoft.DependencyInjection
或者用.NET CLI:
dotnet add package Unity.Microsoft.DependencyInjection
2. 在Program.cs里配置Unity作为DI容器
修改启动代码,让ASP.NET Core使用Unity容器,并加载你原来的Unity配置文件:
var builder = WebApplication.CreateBuilder(args); // 替换原生DI为Unity容器,并加载原有配置 builder.Host.UseUnityServiceProvider(ctx => { var container = new UnityContainer(); // 加载你原来的Unity配置文件(比如叫unity.config) container.LoadConfiguration("unity.config"); return container; }); // 其他WebAPI配置 builder.Services.AddControllers(); var app = builder.Build(); // 中间件配置... app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
这样你就能完全复用原来的Unity XML配置,不需要做任何修改,直接在ASP.NET Core里运行。
注意点提醒
- 用
Type.GetType的时候,一定要确保类型字符串是完整的程序集限定名,格式是命名空间.类型名, 程序集名,比如MyLibrary.Interfaces.IDepartmentManager, MyLibrary,如果是强命名程序集还要加上版本、公钥等,但普通项目用基础格式就够了。 - 生命周期的选择:ASP.NET Core的
Scoped对应Unity的PerRequestLifetimeManager(Web场景下),Transient对应Unity的默认生命周期,Singleton对应Unity的ContainerControlledLifetimeManager。 - 如果用原生DI,尽量避免复杂的DI场景(比如属性注入、自定义生命周期),原生DI更推荐构造函数注入,这也是ASP.NET Core的最佳实践。
内容的提问来源于stack exchange,提问作者granadaCoder
相关产品推荐
相关产品推荐

