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

时间:2010-08-21 03:53:52

标签: c# reflection static properties

我想创建一个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<String, String> kvp = new Dictionary<String, String>();

         // 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"; }
      }
   }
}

5 个答案:

答案 0 :(得分:4)

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

public static PropertyInfo GetProperty(Expression<Func<string>> 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<Func<string>> 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);
}

答案 1 :(得分:2)

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

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

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

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

现在您可以使用以下

来调用它
var bag = GetStaticPropertyBag(typeof(MyResources));

答案 2 :(得分:0)

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

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

有关详细信息,请参阅GetProperties()GetValue()

答案 3 :(得分:0)

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

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

以下是代码的其余部分:

  protected Dictionary<String, String> _javaScriptTokens = new Dictionary<String, String>();

  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<String, String> 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);
  }

我讨厌使用剪切和粘贴硬编码来保持属性名称和密钥同步......好吧......

答案 4 :(得分:0)

其他答案已经解释了如何通过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<string, object> GetStaticPropertyBag(Type t)
{
    var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
    var map = new Dictionary<string, object>();
    foreach (var prop in t.GetProperties(flags))
        if (prop.IsDefined(typeof(WantThisAttribute), true))
            map[prop.Name] = prop.GetValue(null,null);
    return map;
}