How can I get the name of a C# static class property using reflection?

后端 未结 5 1342
孤街浪徒
孤街浪徒 2020-12-11 22:41

I want to make a C# Dictionary in which the key is the string name of a static property in a class and the value is the value of the property. Given a static property in th

相关标签:
5条回答
  • 2020-12-11 22:51

    If all you want is just to be able to refer to a single, specific property in one place in the code without having to refer to it by a literal string, then you can use an expression tree. For example, the following code declares a method that turns such an expression tree into a PropertyInfo object:

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

    Now you can do something like this:

    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);
    }
    
    0 讨论(0)
  • 2020-12-11 22:52

    Here is a function that will get you the names of all static properties in a given type.

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

    If you want to build up the map of all property names to their values you can do the following

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

    Now you can call it with the following

    var bag = GetStaticPropertyBag(typeof(MyResources));
    
    0 讨论(0)
  • 2020-12-11 22:52

    You can accomplish this with reflection. The easiest way to get the property names is to loop over all of them.

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

    See GetProperties() and GetValue() for more specifics.

    0 讨论(0)
  • 2020-12-11 22:54

    Other answers have already explained how you can get a list of the static properties via Reflection. You said you don’t want all of them, only a subset of them. It seems, therefore, that you need a way to distinguish the properties you want from the ones you don’t want. One way to do this is using custom attributes.

    Declare a custom attribute class:

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

    Add this custom attribute to the properties you want:

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

    Iterate over the properties to find the ones you want:

    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;
    }
    
    0 讨论(0)
  • 2020-12-11 23:05

    Well, I'm reluctantly answering my own question because I don't think it's possible to do this for a single static property. Ultimately, I ended up hard-coding the key in the Dictionary using a cut-and-paste of the property name. Here's what I ended up with:

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

    And here's the rest of the code:

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

    I hate having to use cut-and-paste hard-coding to keep the property name and the key in sync...Oh well...

    0 讨论(0)
提交回复
热议问题