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

如何优化.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:47:31