Получить значение поля по строке

Я хочу получить значение поля объекта, используя строку в качестве имени переменной. Я попытался сделать это с отражением:

myobject.GetType().GetProperty("Propertyname").GetValue(myobject, null);

Это работает отлично, но теперь я хочу получить значение "под-свойств":

public class TestClass1
{
    public string Name { get; set; }
    public TestClass2 SubProperty = new TestClass2();
}

public class TestClass2
{
    public string Address { get; set; }
}

Здесь я хочу получить значение Address от объекта TestClass1.

Ответ 1

Вы уже сделали все, что вам нужно сделать, вам просто нужно сделать это дважды:

TestClass1 myobject = ...;
// get SubProperty from TestClass1
TestClass2 subproperty = (TestClass2) myobject.GetType()
    .GetProperty("SubProperty")
    .GetValue(myobject, null);
// get Address from TestClass2
string address = (string) subproperty.GetType()
    .GetProperty("Address")
    .GetValue(subproperty, null);

Ответ 2

попробовать

 myobject.GetType().GetProperty("SubProperty").GetValue(myobject, null)
 .GetType().GetProperty("Address")
 .GetValue(myobject.GetType().GetProperty("SubProperty").GetValue(myobject, null), null);

Ответ 3

Ваш член SubProperty на самом деле является Field, а не Property, поэтому вы не можете получить к нему доступ с помощью метода GetProperty(string). В вашем текущем сценарии вы должны использовать следующий класс, чтобы сначала получить поле SubProperty, а затем свойство Address.

Этот класс позволит вам указать возвращаемый тип вашего свойства, закрыв тип T соответствующим типом. Тогда вам просто нужно добавить к первому параметру объект, члены которого вы извлекаете. Второй параметр - это имя поля, которое вы извлекаете, а третий параметр - имя свойства, значение которого вы пытаетесь получить.

class SubMember<T>
{
    public T Value { get; set; }

    public SubMember(object source, string field, string property)
    {
        var fieldValue = source.GetType()
                               .GetField(field)
                               .GetValue(source);

        Value = (T)fieldValue.GetType()
                             .GetProperty(property)
                             .GetValue(fieldValue, null);
    }
}

Чтобы получить нужное значение в вашем контексте, просто выполните следующие строки кода.

class Program
{
    static void Main()
    {
        var t1 = new TestClass1();

        Console.WriteLine(new SubMember<string>(t1, "SubProperty", "Address").Value);            
    }
}

Это даст вам значение, содержащееся в свойстве Address. Просто убедитесь, что вы сначала добавили значение к указанному свойству.

Но если вы действительно хотите изменить поле своего класса на свойство, тогда вы должны внести следующее изменение в исходный класс SubMember.

class SubMemberModified<T>
{
    public T Value { get; set; }

    public SubMemberModified(object source, string property1, string property2)
    {
        var propertyValue = source.GetType()
                                  .GetProperty(property1)
                                  .GetValue(source, null);

        Value = (T)propertyValue.GetType()
                                .GetProperty(property2)
                                .GetValue(propertyValue, null);
    }
}

Этот класс теперь позволит вам извлечь свойство из вашего начального класса и получить значение из второго свойства, которое извлекается из первого свойства.