如何使用reflection获取C#静态类属性的名称?

我想创建一个C#Dictionary,其中key是类中静态属性的字符串名称,value是属性的值。 给定名为MyResources.TOKEN_ONE的类中的静态属性,如何获取属性的名称而不是其值? 我只关心属性名称的末尾部分(例如“TOKEN_ONE”)。

我编辑过这个,提到我不想映射字典中的所有属性值,只是该类中所有内容的一小部分。 所以假设我想获得单个属性的名称。 给定MyResources.TOKEN_ONE,我想回到“MyResources.TOKEN_ONE”或只是“TOKEN_ONE”。

这是一些示例代码,显示了我正在尝试做的事情。 我需要属性名称,因为我正在尝试生成一个javascript变量,其中我将属性名称映射到变量名称,将属性值映射到变量值。 例如,我希望C#Dictionary生成如下所示的行:

var TOKEN_ONE =“一个”;

using System; using System.Collections.Generic; namespace MyConsoleApp { class Program { static void Main(string[] args) { Dictionary kvp = new Dictionary(); // How can I use the name of static property in a class as the key for the dictionary? // For example, I'd like to do something like the following where 'PropertyNameFromReflection' // is a mechanism that would return "MyResources.TOKEN_ONE" kvp.Add(MyResources.TOKEN_ONE.PropertyNameFromReflection, MyResources.TOKEN_ONE); kvp.Add(MyResources.TOKEN_TWO.PropertyNameFromReflection, MyResources.TOKEN_TWO); Console.ReadLine(); } } public static class MyResources { public static string TOKEN_ONE { get { return "One"; } } public static string TOKEN_TWO { get { return "Two"; } } } } 

如果只需要能够在代码中的某个位置引用单个特定属性不必通过文字字符串引用它,那么您可以使用表达式树。 例如,以下代码声明了一个将这种表达式树转换为PropertyInfo对象的方法:

 public static PropertyInfo GetProperty(Expression> expr) { var member = expr.Body as MemberExpression; if (member == null) throw new InvalidOperationException("Expression is not a member access expression."); var property = member.Member as PropertyInfo; if (property == null) throw new InvalidOperationException("Member in expression is not a property."); return property; } 

现在你可以这样做:

 public void AddJavaScriptToken(Expression> propertyExpression) { var p = GetProperty(propertyExpression); _javaScriptTokens.Add(p.Name, (string) p.GetValue(null, null)); } public void RegisterJavaScriptTokens() { AddJavaScriptToken(() => Tokens.TOKEN_ONE); AddJavaScriptToken(() => Tokens.TOKEN_TWO); } 

这是一个函数,它将为您提供给定类型中所有静态属性的名称。

 public static IEnumerable GetStaticPropertyNames(Type t) { foreach ( var prop in t.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ) { yield return prop.Name; } } 

如果要将所有属性名称的映射构建为其值,可以执行以下操作

 public static Dictionary GetStaticPropertyBag(Type t) { var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); var map = new Dictionary(); foreach ( var prop in t.GetProperties(flags) ) { map[prop.Name] = prop.GetValue(null,null); } return map; } 

现在您可以使用以下内容调用它

 var bag = GetStaticPropertyBag(typeof(MyResources)); 

你可以用reflection完成这个。 获取属性名称的最简单方法是遍历所有属性。

 foreach(var propInfo in this.GetType().GetProperties()) { var name = propInfo.Name; var value = propInfo.GetValue(this, null); } 

有关更多细节,请参阅GetProperties()和GetValue() 。

好吧,我不情愿地回答我自己的问题,因为我觉得不可能为一个静态属性做这个。 最后,我最终使用属性名称的剪切和粘贴对字典中的键进行了硬编码。 这就是我最终得到的结果:

  public void RegisterJavaScriptTokens() { AddJavaScriptToken(Token.FOOBAR_TITLE, "FOOBAR_TITLE"); } 

这是代码的其余部分:

  protected Dictionary _javaScriptTokens = new Dictionary(); public void AddJavaScriptToken(string tokenValue, string propertyName) { _javaScriptTokens.Add(propertyName, tokenValue); } protected override void OnPreRender(EventArgs e) { if (_javaScriptTokens.Count > 0) { StringBuilder sb = new StringBuilder(); foreach (KeyValuePair kvp in _javaScriptTokens) { sb.AppendLine(String.Format("var TOKEN_{0} = unescape('{1}');", kvp.Key, PUtilities.Escape(kvp.Value))); } ClientScript.RegisterStartupScript(this.GetType(), "PAGE_TOKENS", sb.ToString(), true); } base.OnPreRender(e); } 

我不喜欢使用剪切和粘贴硬编码来保持属性名称和密钥同步……哦……

其他答案已经解释了如何通过Reflection获取静态属性列表。 你说你不想要所有这些,只是它们的一部分。 因此,您似乎需要一种方法来区分您想要的属性和您不想要的属性。 一种方法是使用自定义属性。

声明自定义属性类:

 [AttributeUsage(AttributeTargets.Property)] public class WantThisAttribute : Attribute { } 

将此自定义属性添加到所需的属性:

 public static class MyResources { [WantThis] public static string TOKEN_ONE { get { return "One"; } } [WantThis] public static string TOKEN_TWO { get { return "Two"; } } public static string DontWantThis { get { return "Nope"; } } } 

迭代属性以找到您想要的属性:

 public static Dictionary GetStaticPropertyBag(Type t) { var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; var map = new Dictionary(); foreach (var prop in t.GetProperties(flags)) if (prop.IsDefined(typeof(WantThisAttribute), true)) map[prop.Name] = prop.GetValue(null,null); return map; }