You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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)。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:55:48