如何优化.NET反射代码获取程序集内指定类型的全部特性(含MVC控制器与Action)
优化方案:无需Union和Distinct的特性收集方式
嘿,完全理解你想简化这段代码的想法——咱们可以把逻辑整合起来,去掉多余的Union和重复的ToList调用,甚至可以针对性地过滤控制器类型来提升效率。
基础优化版
首先,我们可以在遍历每个类型时,直接把类上的特性和方法上的特性合并,一次性完成收集,这样就不需要先分别收集再做Union了:
var assemblyTypes = Assembly.GetExecutingAssembly().GetTypes(); var myAttributes = assemblyTypes .SelectMany(type => // 合并当前类的特性和其所有方法的特性 type.GetCustomAttributes<MyAttribute>() .Concat(type.GetMethods().SelectMany(method => method.GetCustomAttributes<MyAttribute>())) ) .ToList();
为什么这能替代原来的写法?因为原来的代码是先把所有类特性放到一个列表,再把所有方法特性放到另一个列表,最后用Union合并;而上面的代码是对每个类型,先合并它自身和方法的特性,再把所有类型的合并结果展开成一个大集合,逻辑更连贯,还减少了中间列表的创建开销。
针对MVC控制器的进阶优化
既然你明确是要收集MVC控制器和Action上的特性,那我们可以先过滤出控制器类型(避免遍历程序集中的所有无关类型),甚至可以进一步筛选出真正的Action方法(比如排除静态方法、抽象方法等):
using System.Web.Mvc; // 或者 using Microsoft.AspNetCore.Mvc; 取决于你的MVC版本 // 只筛选出非抽象的控制器类型 var controllerTypes = Assembly.GetExecutingAssembly().GetTypes() .Where(type => typeof(Controller).IsAssignableFrom(type) && !type.IsAbstract); var myAttributes = controllerTypes .SelectMany(type => type.GetCustomAttributes<MyAttribute>() .Concat( // 只筛选出符合Action特征的方法(公共、非静态、非抽象) type.GetMethods() .Where(method => method.IsPublic && !method.IsStatic && !method.IsAbstract) .SelectMany(method => method.GetCustomAttributes<MyAttribute>()) ) ) .ToList();
关于Distinct的说明
你原来的代码用了Distinct,如果你的场景中同一个MyAttribute实例不会同时出现在控制器和Action上(这是绝大多数情况,因为特性通常是直接声明的,每个声明都会生成新的实例),那上面的代码完全可以去掉Distinct。如果确实存在重复实例的特殊场景,再按需加回去即可。
内容的提问来源于stack exchange,提问作者Sauron
相关产品推荐
相关产品推荐

