Установка вложенных свойств через выражение

У меня есть следующий объект:

public class ContactImport { 
    public long Id {get;set;}
    public Contact Contact {get;set;}
    public Company Company {get;set;}
    public Address Address {get;set;}
}

Я хочу иметь возможность динамически устанавливать свойства вложенных объектов на основе выражения, переданного в (Expression<Func<T, dynamic>>).

Для этого у меня есть следующий метод, он отлично работает для установки свойств объекта верхнего уровня (например, Id), но терпит неудачу при попытке установить что-либо для вложенных объектов (например, Contact.FirstName)

public static void SetPropertyValue<T, TProp>(this T target, Expression<Func<T, TProp>> member, TProp value) {
    var selectorExpr = (MemberExpression)(member.Body is UnaryExpression ? ((UnaryExpression)member.Body).Operand : member.Body);
    if (selectorExpr != null) {
        var property = selectorExpr.Member as PropertyInfo;
        if (property != null) {
            property.SetValue(target, value);
        }
     }
 }

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

Метод SetPropertyValue вызывается следующим образом:

public class ImportCheck<T> {

    public int id { get; set; }
    public string Name { get; set; }
    public Type Type { get; set; }
    public bool Required { get; set; }
    public int? MinLength { get; set; }
    public int? MaxLength { get; set; }
    public string Value { get; set; }
    public Expression<Func<T, dynamic>> AssociatedProperty { get; set; }
}


    T pt = (T)Activator.CreateInstance(typeof(T));
    foreach (var m in mapping) {
        pt.SetPropertyValue(m.AssociatedProperty, Convert.ChangeType(m.Value, Nullable.GetUnderlyingType(m.Type) ?? m.Type));
    }

В приведенном выше примере T — это ContactImport, m.AssociatedProperty — это выражение, а mapping — это List<ImportCheck<ContactImport>>.

Обновить

Моя проблема, кажется, сводится к тому факту, что выражение, передаваемое в SetPropertyValue, имеет возвращаемый тип dynamic. Если установлено значение int, а свойство вложенного объекта равно int, тогда все работает. Проблема, с которой я столкнулся, заключается в том, что мне нужно явно указать результат выражения, чтобы он соответствовал типу целевого свойства. Это, однако, оставляет меня с другой проблемой в том, что мне нужен список ImportChecks с возможностью каждого Expression<Func<T,dynamic>> иметь другой тип возврата.


person Gaz    schedule 08.07.2015    source источник
comment
Покажите пример вызова SetPropertyValue.   -  person Sergey Kalinichenko    schedule 09.07.2015
comment
Почему вы не используете SetPropertyValue напрямую? например: «ContactImport.Address.SetPropertyValue(c => c.id, 5)»?   -  person Ali Adlavaran    schedule 09.07.2015
comment
Я взял строку, прежде чем построить выражение свойства, github.com/tbd-develop/roastpotato/blob/master/server/dotnet/ было бы несложно адаптировать это, чтобы дать вам выражение для установки.   -  person tbddeveloper    schedule 09.07.2015
comment
Вложенные свойства обычно подразумевают рекурсию. Если вы можете предоставить хороший, минимальный, полный пример кода, который четко иллюстрирует ваш вопрос, было бы возможно дать фактический ответ. Тем временем мой ответ на этот предыдущий вопрос может дать вам некоторые идеи о том, как действовать дальше. (Он использует отражение вместо выражений и конкретно относится к типам значений, но основные концепции те же).   -  person Peter Duniho    schedule 09.07.2015
comment
@AliAdlavaran Я не могу этого сделать, так как это общий метод, поэтому я использую выражение, таким образом я могу использовать одну и ту же функцию для нескольких разных типов импорта.   -  person Gaz    schedule 09.07.2015
comment
@dasblinkenlight Надеюсь, приведенное выше редактирование поможет установить AssociatedProperty с помощью чего-то вроде x=>x.Contact.FirstName   -  person Gaz    schedule 09.07.2015