反思C#问题

时间:2009-09-28 22:20:09

标签: reflection c#-2.0

我在获取一个属性为另一个类的类的值时遇到问题。

以下是一个例子:

public class Person 
{
    private int age;
    private string name;

    public Person()
    {
        Address = new Address();

    }

    public int Age
    {
        get { return age; }
        set { age = value; }
    }

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public Address Address { get; set; }
}

public class Address
{
    public string street { get; set; }
    public string houseno { get; set; }
}


public class Program
{
    static void Main(string[] args)
    {

        Person person = new Person();
        person.Age = 27;
        person.Name = "Fernando Vezzali";
        person.Address.houseno = "123";
        person.Address.street = "albert street";

        Type type = typeof(Person);

        PropertyInfo[] properties = type.GetProperties();
        foreach (PropertyInfo property in properties)
        {
            Console.WriteLine("{0} = {1}", property.Name, property.GetValue(person, null));

        }
   }
}

但有了这个,我得不到地址的价值。

有人可以帮忙吗?

4 个答案:

答案 0 :(得分:2)

type.GetProperties()只获取那个类型的属性,其中一个是对象Addressstreethouseno不是Person上的属性。

Console.Write...隐式调用每个参数的ToString()。所以你可能会看到“Address - Namespace.Address”作为输出,因为someAddressObject.ToString()将返回类型名称。

在这种特定情况下获得所需内容的最简单方法是覆盖ToString()对象上的Address,以输出对象的一些有意义的字符串表示形式:

public override ToString()
{
    return string.Format("#{0} {1}",
        this.houseno,
        this.street); //returns #123 StreetName
}

如果你真的需要编写对象上每个子对象的每个属性,那可能会变得相当复杂 - 你实际上是在谈论序列化,它会将对象树和每个对象递归。

答案 1 :(得分:2)

考虑到Jason的回答,这是可能的ToString ......

您还可以将返回的反射对象转换为地址以访问完整对象和属性

public class Address
{
    public string street { get; set; }
    public string houseno { get; set; }
    public override ToString() {
        return string.Format("street: {0}, house: {1}", street, houseno);
    }
}

答案 2 :(得分:0)

要么你需要在Address中实现ToString(),如果你对将格式化的字符串作为Address的值返回感到满意,或者你的迭代代码需要检查每个属性以确定该属性的类型是否也公开了属性,并且将其列入进一步检查。

答案 3 :(得分:0)

你的foreach正在迭代所有属性,我相信它隐含地调用ToString来获取值,所以重写Address类的ToString方法,并将属性作为字符串返回。

或者,在foreach中,通过获取属性类型并检查IsValueType或IsClass来测试您的属性是值类型还是类类型。如果IsValueType为false,则迭代该属性的类类型的属性,就像对Person的属性所做的那样。

这样的事情(你可能需要修改才能编译它,但它给你的想法):

Person person = new Person();        
person.Age = 27;        
person.Name = "Fernando Vezzali";        
person.Address.houseno = "123";        
person.Address.street = "albert street";        

Type type = person.GetType();        

PropertyInfo[] properties = type.GetProperties();        
foreach (PropertyInfo property in properties)        
{
    //get the type of this property
    Type tyProperty = property.PropertyType;

    object oValue = property.GetValue(person, null));        

    //if the property is a value
    if (tyProperty.IsValueType)
    {
        Console.WriteLine("{0} = {1}", property.Name, oValue);
    }
    else  //else if property type is a class
    {
        oSubValue = property.GetValue(oValue, null)); 

        //loop through the classes properties
        PropertyInfo[] lstSubProperties = tyProperty.GetProperties();        
        foreach (PropertyInfo propSub in lstSubProperties)        
        {
             Console.WriteLine("{0} = {1}", propSub .Name, oSubValue);  
        }
    }
}