Получить информацию о свойстве из объекта без указания имени свойства в виде строки

По некоторым причинам мне нужно создать Словарь экземпляров PropertyInfo, соответствующих свойствам некоторого класса (назовем его EntityClass).

Хорошо, я могу использовать typeof(EntityClass).GetProperties().

Но мне также нужно определить значение для некоторых конкретных свойств (известных во время компиляции). Обычно я мог сделать одно из следующего:

EntityInstance.PropertyX = Value;
typeof(EntityClass).GetProperty("PropertyX").SetValue(EntityInstance, Value, null);

Чтобы заполнить мой словарь, мне нужно использовать PropertyInfo экземпляров, а не просто устанавливать значения в обычном режиме. Но мне неудобно получать свойства по их строковым именам. Если какой-то EntityClass изменится, вместо ошибок компиляции возникнет много исключений. Итак, я спрашиваю:

Как получить PropertyInfo известного свойства без передачи имени строки? Мне бы очень хотелось, чтобы там было что-то вроде делегатов:

SomeDelegateType MyDelegate = EntityInstance.MethodX;

Идеально:

SomePropertyDelegate MyPropertyDelegate = EntityInstance.PropertyX;

person Daniel Möller    schedule 27.05.2013    source источник
comment
не могли бы вы описать сценарий? Я имею в виду код до и после модификации Entity. Кроме того, как можно ожидать, что переданное значение будет иметь тот же тип свойства после модификации?   -  person Victor Mukherjee    schedule 27.05.2013


Ответы (2)


Что-то вроде этого?

string s = GetPropertyName<User>( x=> x.Name );

public string GetPropertyName<T>(Expression<Func<T, object>> lambda)
{
    var member = lambda.Body as MemberExpression;
    var prop = member.Member as PropertyInfo;
    return prop.Name;
}

or

public PropertyInfo GetPropertyInfo<T>(Expression<Func<T, object>> lambda)
{
    var member = lambda.Body as MemberExpression;
    return member.Member as PropertyInfo;
}

public class User
{
    public string Name { set; get; }
}
person I4V    schedule 27.05.2013
comment
То, что я сделал, выглядит как твоя копия. Подобная логика даже в том же классе User :) - person Mehmet Ataş; 27.05.2013
comment
{"Unable to cast object of type 'System.Linq.Expressions.UnaryExpression' to type 'System.Linq.Expressions.MemberExpression'."} Есть подсказки? - person Daniel Möller; 29.05.2013
comment
@ Дэниел, мне нужна дополнительная информация. класс? как получить доступ к члену? - person I4V; 29.05.2013
comment
Хорошо! Некоторые выражения представлены как Convert(original lambda), а это UnaryExpression. Но Operand из этого UnaryExpression означает MemberExpression. Итак, просто дополнительная проверка типа, и все работает !!! Спасибо!! - person Daniel Möller; 29.05.2013
comment
Я считаю, что использование object вместо типа свойства в Func - это то, что вызывает автоматическое добавление Convert к выражению. Вероятно, общая версия в другом ответе не поднимет этого. В любом случае, оба ответа подходят для того, что мне нужно. - person Daniel Möller; 29.05.2013
comment
Остерегайтесь этого: stackoverflow.com/questions/ 6658669 /! Не очень безопасно .. - person nawfal; 13.12.2013
comment
Его объяснение верно для любого, кто получает ту же ошибку, что и Даниэль. Если вы пытаетесь следовать ему, вот еще один вопрос о переполнении стека, который обеспечивает реализацию - person KyleMit; 17.11.2014
comment
Привет, извините за старый вопрос, но у меня есть сомнения. в вашем примере, где вы предоставляете x => x.Name, как мне получить object экземпляр x? Пожалуйста, помогите мне - person Rakshith Ravi; 16.08.2016

Не уверен, что вам нужно, но, возможно, это поможет вам двигаться дальше.

public class Property<TObj, TProp>
{
    private readonly TObj _instance;
    private readonly PropertyInfo _propInf;

    public Property(TObj o, Expression<Func<TObj, TProp>> expression)
    {
        _propInf = ((PropertyInfo)((MemberExpression)expression.Body).Member);
        _instance = o;
    }

    public TProp Value
    {
        get
        {
            return (TProp)_propInf.GetValue(_instance);
        }
        set
        {
            _propInf.SetValue(_instance, value);
        }
    }
}

public class User
{
    public string Name { get; set; }
}

var user = new User();
var name = new Property<User, string>(user, u => u.Name);
name.Value = "Mehmet";
Console.WriteLine(name.Value == user.Name); // Prints True
person Mehmet Ataş    schedule 27.05.2013