关于通过Reflection访问C# 14静态扩展方法与扩展属性的技术问询
关于通过Reflection访问C# 14静态扩展方法与扩展属性的技术问询
嘿,这个问题我刚好在尝鲜C#14的时候踩过坑!确实目前官方文档这块讲得不够细,我来给你捋清楚怎么用反射搞定这些扩展成员:
先搞懂编译后的本质
C#14的extension块其实是个语法糖——编译器不会保留这个块本身的任何信息,里面定义的所有成员都会被提升到所在的静态类中,变成带特殊标记的静态成员。核心标记就是System.Runtime.CompilerServices.ExtensionAttribute,所有扩展方法、扩展属性的访问器都会带上这个特性。
一、反射访问C#14扩展方法
就拿你给出的WordCount扩展方法举例,编译后它会变成MyExtensions类里的静态方法,并且带有ExtensionAttribute。你可以这么找到并调用它:
using System.Reflection; using System.Runtime.CompilerServices; // 筛选出带ExtensionAttribute的静态方法 var wordCountMethod = typeof(MyExtensions) .GetMethods(BindingFlags.Static | BindingFlags.Public) .First(m => m.Name == "WordCount" && m.GetCustomAttribute<ExtensionAttribute>() != null); // 调用扩展方法:第一个参数必须是扩展的目标对象(比如string实例) var result = wordCountMethod.Invoke(null, new object[] { "Hello! How are you today?" }); Console.WriteLine(result); // 输出 5
二、反射识别并访问扩展属性
你提到看到了get_WordCount方法,这说明你定义的是扩展属性(如果是方法的话编译后不会带get_前缀)。这里要注意:编译器不会为扩展属性生成真正的PropertyInfo,只会生成带ExtensionAttribute且标记了IsSpecialName=true的get_XXX/set_XXX静态方法。
你可以通过这两个特征来区分普通静态方法和扩展属性的访问器,而不用只靠命名约定:
var myExtensionsType = typeof(MyExtensions); // 拿到所有带ExtensionAttribute的静态成员 var extensionMembers = myExtensionsType .GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) .Where(m => m.GetCustomAttribute<ExtensionAttribute>() != null); // 筛选出扩展属性的get访问器 var extensionPropertyGetters = extensionMembers .Where(m => m.IsSpecialName && // 编译器给属性访问器加的特殊标记 m.Name.StartsWith("get_")) .Select(m => new { PropertyName = m.Name.Substring(4), // 去掉get_前缀得到属性名 GetMethod = m, TargetType = m.GetParameters()[0].ParameterType // 扩展的目标类型,比如string }); // 调用WordCount扩展属性的get方法 var wordCountGetter = extensionPropertyGetters.First(p => p.PropertyName == "WordCount"); var count = wordCountGetter.GetMethod.Invoke(null, new object[] { "This is a test sentence." }); Console.WriteLine(count); // 输出 5
关键总结
- 别找
extension块本身:编译后它就消失了,所有成员都直接属于外层的静态类 - 靠
ExtensionAttribute识别扩展成员:这是最可靠的标记,比命名约定靠谱 - 扩展属性没有原生
PropertyInfo:必须通过对应的get_/set_方法来访问,记得检查IsSpecialName来确认是属性访问器而非普通方法




