如何在C#中动态获取当前命名空间并通过变量访问其成员?
如何获取当前命名空间并通过变量访问其成员?
首先得明确一点:命名空间本身不是可直接实例化的对象,没法像你期望的那样直接通过GetCurrentNameSpace()返回的对象去访问成员——我们得借助反射来实现类似的效果。下面一步步拆解实现方案:
1. 先拿到当前命名空间的字符串
你已经有一段可行的代码,这里再补充两种更灵活的写法:
// 方式1:在实例方法里通过MethodInfo获取 string currentNamespace = MethodInfo.GetCurrentMethod().ReflectedType.Namespace; // 方式2:直接用typeof指定当前类,静态/实例方法都兼容 string currentNamespace = typeof(YourCurrentClass).Namespace;
第二种写法更直观,还能避免反射获取MethodInfo的微小性能开销。
2. 通过命名空间筛选对应类型
拿到命名空间字符串后,我们可以从当前程序集里筛选出该命名空间下的所有类型:
Assembly currentAssembly = Assembly.GetExecutingAssembly(); // 筛选出当前命名空间下的所有类型 IEnumerable<Type> namespaceTypes = currentAssembly.GetTypes() .Where(t => t.Namespace == currentNamespace);
3. 访问类型的成员(静态/实例)
访问静态成员
假设你要访问的variable1是当前命名空间下MyClass类的静态字段,代码可以这么写:
// 先定位到目标类型 Type targetType = namespaceTypes.FirstOrDefault(t => t.Name == "MyClass"); if (targetType != null) { // 获取静态字段的值(BindingFlags要匹配成员的访问修饰符) object variableValue = targetType.GetField("variable1", BindingFlags.Public | BindingFlags.Static)?.GetValue(null); if (variableValue != null) { Console.WriteLine(variableValue.ToString()); } }
如果是静态属性,把GetField换成GetProperty即可。
访问实例成员
如果variable1是实例字段/属性,需要先创建类的实例再访问:
if (targetType != null) { // 创建类的实例(如果有构造参数,需要在CreateInstance中传入对应值) object instance = Activator.CreateInstance(targetType); // 获取实例属性的值 object instanceValue = targetType.GetProperty("variable1", BindingFlags.Public | BindingFlags.Instance)?.GetValue(instance); if (instanceValue != null) { Console.WriteLine(instanceValue.ToString()); } }
4. 封装成接近你期望的写法
如果你想让用法更贴近this.GetCurrentNameSpace().variable1.ToString(),可以用动态类型(dynamic)封装辅助类,把反射逻辑隐藏起来:
public static class NamespaceHelper { // 给对象添加扩展方法,返回当前命名空间的包装对象 public static dynamic GetCurrentNamespace(this object obj) { string ns = obj.GetType().Namespace; var types = Assembly.GetExecutingAssembly().GetTypes() .Where(t => t.Namespace == ns); return new NamespaceWrapper(types); } } // 包装命名空间下的所有类型 public class NamespaceWrapper : DynamicObject { private readonly IEnumerable<Type> _types; public NamespaceWrapper(IEnumerable<Type> types) => _types = types; // 拦截成员访问,匹配对应的类型 public override bool TryGetMember(GetMemberBinder binder, out object result) { Type targetType = _types.FirstOrDefault(t => t.Name == binder.Name); if (targetType != null) { result = new TypeWrapper(targetType); return true; } result = null; return false; } } // 包装类型的成员 public class TypeWrapper : DynamicObject { private readonly Type _type; public TypeWrapper(Type type) => _type = type; // 拦截成员访问,获取静态字段/属性 public override bool TryGetMember(GetMemberBinder binder, out object result) { // 先尝试匹配静态字段 var field = _type.GetField(binder.Name, BindingFlags.Public | BindingFlags.Static); if (field != null) { result = field.GetValue(null); return true; } // 再尝试匹配静态属性 var property = _type.GetProperty(binder.Name, BindingFlags.Public | BindingFlags.Static); if (property != null) { result = property.GetValue(null); return true; } result = null; return false; } }
现在你就能这样使用了:
// 在当前命名空间的类中调用 dynamic currentNs = this.GetCurrentNamespace(); string value = currentNs.MyClass.variable1.ToString();
注意事项
- 动态类型和反射会带来一定性能开销,且编译时无类型检查,容易出现运行时错误;
- 如果目标类型是已知的,直接用
typeof(MyClass)或直接引用类会更高效、更安全。
内容的提问来源于stack exchange,提问作者Emily Wong
相关产品推荐
相关产品推荐

