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

.NET运行时泛型依赖注入:根据FileType动态调用ICleanerService

解决方案

1. FileType与DTO/DTOMap的映射

直接用类型字典建立枚举与对应类型的关联,无需给DTO额外定义接口,避免冗余设计。可以选择静态字典或注入单例两种方式:

方式1:静态字典(简单场景)

// 可放在ExcelService内部或单独的配置类中
private static readonly Dictionary<FileType, (Type DtoType, Type MapType)> _typeMappings = new()
{
    { FileType.SMALL_EXCEL, (typeof(DTO), typeof(DTOMap)) },
    { FileType.LARGE_EXCEL, (typeof(DTO2), typeof(DTO2Map)) }
};

方式2:注入单例字典(灵活扩展场景)

如果后续需要从配置文件或数据库读取映射关系,可将字典注册为单例服务:

// Program.cs 中注册
var typeMappings = new Dictionary<FileType, (Type DtoType, Type MapType)>
{
    { FileType.SMALL_EXCEL, (typeof(DTO), typeof(DTOMap)) },
    { FileType.LARGE_EXCEL, (typeof(DTO2), typeof(DTO2Map)) }
};
services.AddSingleton(typeMappings);

2. 运行时获取对应ICleanerService并调用方法

通过IServiceProvider结合反射,动态构造泛型服务类型并调用方法:

步骤1:ExcelService注入依赖

public class ExcelService : IExcelService 
{
    private readonly IServiceProvider _serviceProvider;
    private readonly Dictionary<FileType, (Type DtoType, Type MapType)> _typeMappings;

    // 注入服务提供器和映射字典(如果用静态字典则无需注入后者)
    public ExcelService(IServiceProvider serviceProvider, Dictionary<FileType, (Type, Type)> typeMappings)
    {
        _serviceProvider = serviceProvider;
        _typeMappings = typeMappings;
    }

步骤2:动态调用CleanObject方法

public async Task<bool> TransformExcel(FileType fileType, string path) 
    {
        if (!_typeMappings.TryGetValue(fileType, out var types))
        {
            throw new ArgumentException($"不支持的文件类型:{fileType}");
        }

        // 构造泛型服务类型:ICleanerService<T, V>
        var cleanerServiceType = typeof(ICleanerService<,>).MakeGenericType(types.DtoType, types.MapType);
        
        // 从容器获取服务实例
        var cleanerService = _serviceProvider.GetService(cleanerServiceType);
        if (cleanerService == null)
        {
            throw new InvalidOperationException($"未注册对应的ICleanerService:{cleanerServiceType.FullName}");
        }

        // 调用异步的CleanObject方法
        var cleanMethod = cleanerServiceType.GetMethod(nameof(ICleanerService<object, object>.CleanObject));
        var taskResult = (Task<List<object>>)cleanMethod.Invoke(cleanerService, new object[] { path });
        var resultList = await taskResult;

        // 根据业务需求返回结果,示例为返回是否有清理后的数据
        return resultList != null && resultList.Count > 0;
    }
}

优化:封装通用调用逻辑

如果多处需要动态调用泛型服务,可封装工具类减少重复代码:

public static class CleanerServiceHelper
{
    public static async Task<List<object>> CleanAsync(this IServiceProvider provider, FileType fileType, string path, Dictionary<FileType, (Type, Type)> mappings)
    {
        if (!mappings.TryGetValue(fileType, out var types))
            throw new ArgumentException($"不支持的文件类型:{fileType}");
        
        var serviceType = typeof(ICleanerService<,>).MakeGenericType(types.Item1, types.Item2);
        var service = provider.GetService(serviceType) ?? throw new InvalidOperationException($"未注册服务:{serviceType}");
        
        var method = serviceType.GetMethod(nameof(ICleanerService<object, object>.CleanObject)) ?? throw new MissingMethodException("找不到CleanObject方法");
        return await (Task<List<object>>)method.Invoke(service, new[] { path });
    }
}

之后ExcelService可简化为:

public async Task<bool> TransformExcel(FileType fileType, string path) 
{
    var result = await _serviceProvider.CleanAsync(fileType, path, _typeMappings);
    return result != null && result.Count > 0;
}

内容的提问来源于stack exchange,提问作者Gerard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 15:55:52