【问题标题】:How can I get the value of a string property via Reflection?如何通过反射获取字符串属性的值?
【发布时间】:2010-11-02 13:05:16
【问题描述】:
public class Foo
{
   public string Bar {get; set;}
}

如何通过反射获取字符串属性 Bar 的值?如果 PropertyInfo 类型是 System.String,则以下代码将引发异常

Foo f = new Foo();
f.Bar = "Jon Skeet is god.";

foreach(var property in f.GetType().GetProperties())
{
 object o = property.GetValue(f,null); //throws exception TargetParameterCountException for String type
}

看来我的问题是该属性是索引器类型,带有 System.String。

另外,如何判断属性是否为索引器?

【问题讨论】:

  • 在这里工作正常......还有其他事情发生吗?
  • 您似乎没有发布足够的上下文代码?
  • 是的。调试器说底层类型是字符串,但我怀疑还有其他事情发生。

标签: c# string reflection properties


【解决方案1】:

您可以通过名称获取属性:

Foo f = new Foo();
f.Bar = "Jon Skeet is god.";

var barProperty = f.GetType().GetProperty("Bar");
string s = barProperty.GetValue(f,null) as string;

关于后续问题: 索引器将始终命名为 Item 并在 getter 上有参数。 所以

Foo f = new Foo();
f.Bar = "Jon Skeet is god.";

var barProperty = f.GetType().GetProperty("Item");
if (barProperty.GetGetMethod().GetParameters().Length>0)
{
    object value = barProperty.GetValue(f,new []{1/* indexer value(s)*/});
}

【讨论】:

  • 那不准确。 Item 是索引器的默认名称,但任何人都可以使用索引器属性上的 IndererNameAttribute 来更改它。您必须在类型上查找 DefaultMemberAttribute 才能获得实际的索引器名称。
  • 我完全不知道 IndexerName 属性!谢谢你。您可以在此处找到更多信息:bartdesmet.net/blogs/bart/archive/2006/09/09/4408.aspx 谢谢 Jb Evain。
  • 如果我只有一个具有完整类名的字符串,以及像 MyNameSpace1.X.Y.Z.ClassName 和 PropertyName 这样的属性名称?
【解决方案2】:

我无法重现该问题。您确定您没有尝试在某些具有索引器属性的对象上执行此操作吗?在这种情况下,您在处理 Item 属性时会抛出您遇到的错误。 另外,您可以这样做:


public static T GetPropertyValue<T>(object o, string propertyName)
{
      return (T)o.GetType().GetProperty(propertyName).GetValue(o, null);
}

...somewhere else in your code...
GetPropertyValue<string>(f, "Bar");

【讨论】:

    【解决方案3】:
    Foo f = new Foo();
    f.Bar = "x";
    
    string value = (string)f.GetType().GetProperty("Bar").GetValue(f, null);
    

    【讨论】:

      【解决方案4】:
      var val = f.GetType().GetProperty("Bar").GetValue(f, null);
      

      【讨论】:

        【解决方案5】:
        Foo f = new Foo();
        f.Bar = "Jon Skeet is god.";
        
        foreach(var property in f.GetType().GetProperties())
        {
            if(property.Name != "Bar")
            {
                 continue;
            }
            object o = property.GetValue(f,null); //throws exception TargetParameterCountException for String type
        }
        

        这是后续行动:

        class Test
        {
            public class Foo
            {
                Dictionary<string, int> data =new Dictionary<string,int>();
                public int this[string index]
                {
                    get { return data[index]; }
                    set { data[index] = value; }
                }
        
                public Foo()
                {
                    data["a"] = 1;
                    data["b"] = 2;
                }
            }
        
            public Test()
            {
                var foo = new Foo();
                var property = foo.GetType().GetProperty("Item");
                var value = (int)property.GetValue(foo, new object[] { "a" });
                int i = 0;
            }
        }
        

        【讨论】:

        • 基于其他 cmets,您需要将 get 值的 null 更改为正确的索引器值。
        【解决方案6】:
        PropertyInfo propInfo = f.GetType().GetProperty("Bar");
        object[] obRetVal = new Object[0];
        string bar = propInfo.GetValue(f,obRetVal) as string;
        

        【讨论】:

        • 反对票到底是为了什么?此代码按预期工作。
        【解决方案7】:

        任意对象的属性值很容易通过如下扩展方法获取:

        public static class Helper
            {
                public static object GetPropertyValue(this object T, string PropName)
                {
                    return T.GetType().GetProperty(PropName) == null ? null : T.GetType().GetProperty(PropName).GetValue(T, null);
                }
            }
        

        用法是:

        Foo f = new Foo();
        f.Bar = "x";
        var balbal = f.GetPropertyValue("Bar");
        

        【讨论】:

        【解决方案8】:

        带有 object 和 null 的 getvalue 对我来说非常有用。感谢您的帖子。

        上下文:循环遍历新员工的 MVC 模型中的所有属性并确定它们的表单发布值:

        newHire => 模型,具有许多属性,我想将其发布的表单值单独写入一组数据库记录

        foreach(var propertyValue in newHire.GetProperties())
        {
        string propName = propertyValue.Name;
        
        string postedValue = newHire.GetType().GetProperty(propName).GetValue(newHire, null).ToString();
        
        }
        

        【讨论】:

        • 这个简单的答案救了我的命。谢谢!
        【解决方案9】:

        要通过仅传递对象来获取对象的属性名称,您可以使用此函数可能会起作用。

        只需将 object 对象变成一个类并传递给它。

         public void getObjectNamesAndValue(object obj)
            {
                Type type = obj.GetType();
                BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
                PropertyInfo[] prop = type.GetProperties(flags);
                foreach (var pro in prop)
                {
                    System.Windows.Forms.MessageBox.Show("Name :" + pro.Name + " Value : "+  pro.GetValue(obj, null).ToString());
                }
        
            }
        

        但这仅在对象属性为“公共”时才有效

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-01-27
          • 1970-01-01
          • 2010-11-08
          • 2023-03-28
          • 1970-01-01
          • 2010-11-14
          相关资源
          最近更新 更多