使用反射在类实例中通过名称获取属性的值

9
假设我有:
class Person
{
    public Person(int age, string name)
    {
        Age = age;
        Name = name; 
    }
    public int Age{get;set}
    public string Name{get;set}
}

我将创建一个方法,接受包含“age”或“name”的字符串,并返回具有该属性值的对象。
就像以下伪代码一样:
    public object GetVal(string propName)
    {
        return <propName>.value;  
    }

如何使用反射来实现这个功能?

我正在使用asp.net 3.5和c# 3.5进行编码。


3
问问自己,强类型访问是否是更好的选择。大多数情况下都是这样。 - ChaosPandion
1
请记住,您展示的类别实际上没有任何属性。它有两个字段。字段和属性之间有很大的区别 - 您真正感兴趣的是哪一个? - Jon Skeet
@jon - 实际上是属性。让我编辑我的问题。 - TheMoot
@TheMoot - 请记住,我的建议非常通用,因为我不知道您程序的逻辑。这可能意味着对现有逻辑进行完全重写,在许多情况下是不可行的。 - ChaosPandion
@TheMoot - 强类型访问意味着避免使用“magic strings”来获取属性值。换句话说,直接使用属性而不是添加间接层。 (这可能对您的应用程序可行也可能不可行)。 - Ryan Emerle
显示剩余2条评论
4个回答

15

我认为这是正确的语法...

var myPropInfo = myType.GetProperty("MyProperty");
var myValue = myPropInfo.GetValue(myInstance, null);

我没有编辑权限,但你的第二行 var myValue = propertyInfo.GetValue(myInstance, null); 应该说 myproperty.Info 等等。谢谢,然后它就起作用了。 - TheMoot

4

首先,您提供的示例没有属性。它有私有成员变量。对于属性,您将会有类似以下的内容:

public class Person
{
    public int Age { get; private set; }
    public string Name { get; private set; }

    public Person(int age, string name)
    {
        Age = age;
        Name = name;
    }
}

然后使用反射来获取值:

 public object GetVal(string propName)
 {
     var type = this.GetType();
     var propInfo = type.GetProperty(propName, BindingFlags.Instance);
     if(propInfo == null)
         throw new ArgumentException(String.Format(
             "{0} is not a valid property of type: {1}",
             propName, 
             type.FullName));

     return propInfo.GetValue(this);
 }

请记住,虽然您已经可以访问类及其属性(因为您也可以访问方法),但直接使用属性要比通过反射执行某些花哨操作更容易。


抱歉,Jon 指出了这一点。我编辑了我的例子。我把这个例子简化得有些过头了。 - TheMoot
示例代码假定缺少属性和具有值“null”的属性是等效的。如果给定的propName没有映射到属性,您可能需要抛出ArgumentException - Ryan Emerle

2
您可以像这样做:

您可以像这样做:

Person p = new Person( 10, "test" );

IEnumerable<FieldInfo> fields = typeof( Person ).GetFields( BindingFlags.NonPublic | BindingFlags.Instance );

string name = ( string ) fields.Single( f => f.Name.Equals( "name" ) ).GetValue( p );
int age = ( int ) fields.Single( f => f.Name.Equals( "age" ) ).GetValue( p );

请记住,由于这些是私有实例字段,您需要明确声明绑定标志才能通过反射获取它们。
编辑:
看起来你把示例从使用字段改为使用属性,所以我会把这个留在这里,以防你再次更改。 :)

我修改了我的示例,因为我把它简化得有点过头了。但是你的答案可能对其他领域也有用,所以谢谢你,我会给你投票支持的。 - TheMoot

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接