如何通过反射调用实现泛型接口的类中的方法
调用泛型接口实现类方法的延迟绑定异常问题
我希望调用当前程序集中实现特定泛型接口的对象方法,现有条件:
- 泛型接口
IMyContract<T>(T为类); - 两个模型类:
MyContractModel和MyContractModel2; - 两个服务类:
MyContractService实现IMyContract<MyContractModel>,MyContractService2实现IMyContract<MyContractModel2>; - 已通过
services.AddSingleton将服务注册到依赖注入容器中。
目前能从程序集中获取正确的接口类型,并从依赖注入中加载服务实例,但调用方法时因编译器无法识别类型出现延迟绑定异常。请问该操作是否可行?若不可行,给出替代方案。
现有代码
// Register services var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton<IMyContract<MyContractModel>, MyContractService>(); serviceCollection.AddSingleton<IMyContract<MyContractModel2>, MyContractService2>(); var serviceProvider = serviceCollection.BuildServiceProvider(); // Load all contract processors (that implement `IMyContract`) and invoke `Process` on them var iContractPrcessor = typeof(IMyContract<>); IEnumerable<Type> allTypesInThisAssembly = Assembly.GetExecutingAssembly().GetTypes(); foreach(Type type in allTypesInThisAssembly) { if (type.GetInterface(iContractPrcessor.Name.ToString()) != null) { // As expected in 1st iteration, produces IMyContract<MyContractModel> Type implementedInterface = type.GetInterface(iContractPrcessor.Name.ToString()); // As expected in 1st iteration, produces MyContractService var contractService = serviceProvider.GetService(implementedInterface); MethodInfo method = iContractPrcessor.GetMethod("Process"); //This throws an exception: late bound operation exception var result = (Task) method.Invoke(contractService, null); await result.ConfigureAwait(false); } } public interface IMyContract<T> where T : class { Task Process(); } public class MyContractModel { public string Name { get; set; } = ""; } public class MyContractService : IMyContract<MyContractModel> { public Task Process() { Console.WriteLine("MyContractService Process"); return Task.CompletedTask; } } public class MyContractModel2 { public string Name { get; set; } = ""; } public class MyContractService2 : IMyContract<MyContractModel2> { public Task Process() { Console.WriteLine("MyContractService2 Process"); return Task.CompletedTask; } }
解决方案
问题原因
直接从开放泛型类型IMyContract<>获取Process方法,再用它调用具体泛型实现类的实例会触发延迟绑定异常——开放泛型的方法与具体封闭泛型(如IMyContract<MyContractModel>)的方法并非同一个MethodInfo实例,无法跨类型调用。
可行方案
方案1:修正反射调用逻辑
循环中拿到具体的封闭泛型接口(implementedInterface)后,从该接口类型获取Process方法,而非从开放泛型类型获取:
foreach(Type type in allTypesInThisAssembly) { // 仅处理具体服务类,排除接口、抽象类 if (type.IsClass && !type.IsAbstract) { // 筛选出实现了IMyContract<>的封闭泛型接口 var implementedInterfaces = type.GetInterfaces() .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMyContract<>)); foreach(var implementedInterface in implementedInterfaces) { var contractService = serviceProvider.GetService(implementedInterface); if (contractService == null) continue; // 从具体封闭泛型接口获取方法 MethodInfo method = implementedInterface.GetMethod("Process"); if (method == null) continue; var result = (Task)method.Invoke(contractService, null); await result.ConfigureAwait(false); } } }
方案2:引入非泛型基接口(更简洁优雅)
给泛型接口定义一个非泛型基接口,让所有泛型实现类自动继承该接口,从而避免反射,直接通过依赖注入获取实例并调用方法:
// 新增非泛型基接口 public interface IMyContract { Task Process(); } // 泛型接口继承非泛型基接口 public interface IMyContract<T> : IMyContract where T : class { // 可在此添加泛型特有的方法,Process已在基接口定义 } // 服务类无需修改,自动实现IMyContract接口 public class MyContractService : IMyContract<MyContractModel> { public Task Process() { Console.WriteLine("MyContractService Process"); return Task.CompletedTask; } } // 调用逻辑简化 var allContractServices = serviceProvider.GetServices<IMyContract>(); foreach(var service in allContractServices) { await service.Process().ConfigureAwait(false); }
该方案性能更优,代码可读性更强,完全规避了反射的复杂性。
内容的提问来源于stack exchange,提问作者Khaled Hikmat
相关产品推荐
相关产品推荐

