.NET Core运行时创建类实例返回Null问题求助
运行时创建带构造参数的类实例失败问题
场景说明
我在.NET Core后台服务中尝试动态创建类库MyApp.Service中的WeeklyTaskSchedular实例并调用其方法,但始终无法获取到该类型(GetInstance返回null),具体代码如下:
类库MyApp.Service代码
namespace MyApp.Service.SchedularOperations { public class WeeklyTaskSchedular : ISchedular { private readonly IDbConnection _dbConnection; private readonly IProductService _productService; public WeeklyTaskSchedular(IDbConnection dbConnection,IProductService productService) { _dbConnection = dbConnection; _productService = productService; Frequency = Frequencies.Weekly; } public Frequencies Frequency { get ; set ; } public int Process (ScheduleInfo info) { // 业务处理逻辑 return 0; // 表示成功 } } }
BackgroundService项目代码
namespace MyApp.BackgroundSchedularService { public class RunSchedular : BackgroundService { private readonly ILogger<RunSchedular> _logger; private readonly IProductService _productService; public RunSchedular(ILogger<RunSchedular> logger, IProductService productService) { _logger = logger; _productService = productService; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { string connectionString = GetThirdPartyConnectionStringFromDatabase(); string executionClassName = "MyApp.Service.SchedularOperations.WeeklyTaskSchedular"; // 从数据库获取 IDbConnection connection = new SqlConnection(connectionString); object[] constructorArgs = { connection, _productService}; Type type = GetInstance(executionClassName); // 此处返回null object instance = Activator.CreateInstance(type,constructorArgs); object[] methodArgs = { new ScheduleInfo() }; type.GetMethod("Process").Invoke(instance,methodArgs); await Task.Delay(1000, stoppingToken); } } public Type GetInstance(string strFullyQualifiedName) { foreach(var asm in AppDomain.CurrentDomain.GetAssemblies()) { Type type = asm.GetType(strFullyQualifiedName); if(type !=null) return type; } return null; } } } public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddHostedService<RunSchedular>(); services.AddTransient<IProductService, ProductService>(); }); }
当前核心问题
Type type = GetInstance(executionClassName); 该行返回null,无法获取目标类型,导致后续实例创建失败。
解决方案
1. 确保类库已被正确加载
.NET Core中,AppDomain.CurrentDomain.GetAssemblies()只会返回当前已加载到应用程序域的程序集,如果MyApp.Service程序集未被提前引用或加载,就会找不到类型。
- 解决方式:
- 若为同一解决方案,直接在BackgroundService项目中添加对
MyApp.Service的项目引用; - 若为独立发布的类库,可手动加载程序集:
public Type GetInstance(string strFullyQualifiedName, string assemblyPath) { // 先从已加载程序集查找 foreach(var asm in AppDomain.CurrentDomain.GetAssemblies()) { Type type = asm.GetType(strFullyQualifiedName); if(type !=null) return type; } // 加载指定路径的程序集并查找类型 var assembly = Assembly.LoadFrom(assemblyPath); return assembly.GetType(strFullyQualifiedName); }
注意:若使用
Assembly.Load,需传入程序集全名(如MyApp.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null)。 - 若为同一解决方案,直接在BackgroundService项目中添加对
2. 校验全限定类名准确性
确认executionClassName的拼写完全匹配类的命名空间+类名,反射API对大小写敏感,需严格对应。
3. 结合依赖注入优化实例创建
如果类依赖已注册的服务(如IProductService),可利用DI容器自动解析依赖,避免手动处理构造参数:
- 修改
RunSchedular注入IServiceProvider:public class RunSchedular : BackgroundService { private readonly ILogger<RunSchedular> _logger; private readonly IServiceProvider _serviceProvider; public RunSchedular(ILogger<RunSchedular> logger, IServiceProvider serviceProvider) { _logger = logger; _serviceProvider = serviceProvider; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { string connectionString = GetThirdPartyConnectionStringFromDatabase(); string executionClassName = "MyApp.Service.SchedularOperations.WeeklyTaskSchedular"; Type type = GetInstance(executionClassName); if(type == null) { _logger.LogError("无法找到类型:{TypeName}", executionClassName); await Task.Delay(1000, stoppingToken); continue; } // 利用DI容器解析已注册服务,同时传入自定义参数 using var scope = _serviceProvider.CreateScope(); var instance = ActivatorUtilities.CreateInstance(scope.ServiceProvider, type, new SqlConnection(connectionString)); // 调用Process方法 var processMethod = type.GetMethod("Process"); if(processMethod != null) { var result = processMethod.Invoke(instance, new object[] { new ScheduleInfo() }); _logger.LogInformation("Process方法执行结果:{Result}", result); } await Task.Delay(1000, stoppingToken); } } // GetInstance方法保持或优化为上述加载程序集的版本 public Type GetInstance(string strFullyQualifiedName) { foreach(var asm in AppDomain.CurrentDomain.GetAssemblies()) { Type type = asm.GetType(strFullyQualifiedName); if(type !=null) return type; } return null; } }ActivatorUtilities.CreateInstance会自动从DI容器中解析构造函数内的已注册服务,同时支持传入自定义参数(如示例中的SqlConnection)。
4. 添加错误处理与日志
在代码中增加异常捕获和日志输出,便于快速定位问题:
try { Type type = GetInstance(executionClassName); if(type == null) { _logger.LogError("未找到类型:{TypeName}", executionClassName); continue; } // 后续实例创建和方法调用逻辑 } catch(Exception ex) { _logger.LogError(ex, "创建实例或调用方法时出错"); }
内容的提问来源于stack exchange,提问作者I Love Stackoverflow
相关产品推荐
相关产品推荐

