C#10调用实现IEndpoint接口的所有类的Map方法相关问题咨询
错误原因
你最初的报错是因为Assembly.GetTypes()返回的是程序集中所有类型的Type元数据对象,筛选后得到的是IEnumerable<Type>集合,而你尝试直接赋值给IEnumerable<IEndpoint>类型的变量,二者类型不匹配,自然无法隐式转换。
你更新后代码的问题
目前的实现存在几个明显遗漏:
IsAssignableFrom判断逻辑写反:x.IsAssignableFrom(typeof(IEndpoint))的含义是判断IEndpoint类型能不能赋值给x类型,这只能匹配IEndpoint本身或者它的父接口,完全筛选不到你要的实现类。正确写法是typeof(IEndpoint).IsAssignableFrom(x),判断x类型的实例能不能赋值给IEndpoint类型的变量。- 缺少类型合法性校验:你只排除了接口,没有排除抽象类、未构造的泛型类型,这些类型都无法直接实例化,会触发运行时异常。
- 实例化逻辑没有容错:
Activator.CreateInstance要求目标类必须有公共无参构造函数,如果你的实现类依赖其他注入服务,没有无参构造的话会直接抛出异常。
修复后的完整实现
// 筛选符合要求的实现类 IEnumerable<Type> endpointTypes = typeof(Program).Assembly .GetTypes() .Where(x => // 确认实现了IEndpoint接口 typeof(IEndpoint).IsAssignableFrom(x) // 排除接口、抽象类 && x.IsClass && !x.IsAbstract && !x.IsInterface // 排除未构造的泛型类型 && !x.ContainsGenericParameters); foreach (Type type in endpointTypes) { try { // 实例化并调用Map方法 if (Activator.CreateInstance(type) is IEndpoint endpoint) { endpoint.Map(); } } catch (MissingMethodException) { // 处理没有无参构造函数的情况,可按需增加日志 continue; } }
更推荐的方案(适配依赖注入场景)
如果你用的是ASP.NET Core这类带依赖注入的框架,不建议直接用Activator.CreateInstance实例化,更好的方式是把所有IEndpoint实现类注册到DI容器,再直接从容器获取实例,自动处理构造函数的依赖注入:
// 注册所有IEndpoint实现 var services = new ServiceCollection(); foreach (var type in endpointTypes) { services.AddTransient(typeof(IEndpoint), type); } // 构建容器后直接获取所有实例 var serviceProvider = services.BuildServiceProvider(); var endpoints = serviceProvider.GetServices<IEndpoint>(); foreach (var endpoint in endpoints) { endpoint.Map(); }
内容的提问来源于stack exchange,提问作者Miguel Moura
相关产品推荐
相关产品推荐

