Как я могу передать несколько лямбда-выражений в метод, а затем получить информацию о свойствах для каждого выражения? - PullRequest
0 голосов
/ 04 марта 2019

В проекте на C # я хочу создать функцию, которая позволит мне передавать лямбда-выражение, которое я могу проанализировать, каждое выражение в PropertyInfo, где я могу извлечь имя свойства и значение свойства.

Здесьурезанная версия моего кода

public IEnumerable<Student> Make(IEnumerable<User> users, Expression<Func<User, dynamic>> primaryProperty, params Expression<Func<User, dynamic>>[] otherProperties)
{
    var students = new List<Student>();

    foreach(User user in users)
    {
        var student = new Student();
        var mainProp = GetPropertyInfo(user, primaryProperty);
        object mainValue = prop.GetValue(user, null);
        // Do somthing with mainProp.Name...
        // Do something with mainValue ...

        foreach(Expression<Func<User, dynamic> exp in otherProperties ?? new Expression<Func<User, dynamic>>[] {})
        {
            var prop = GetPropertyInfo(user, exp);
            object value = prop.GetValue(user, null);
            // Set the property student property
            // Do somthing with prop.Name...
            // Do something with value...
        }

        students.Add(student);
    }

    return strudents;
}


private static PropertyInfo GetPropertyInfo<TSource, TProperty>(TSource source, Expression<Func<TSource, TProperty>> propertyLambda)
{
    Type type = typeof(TSource);

    if (!(propertyLambda.Body is MemberExpression expression))
    {
        throw new ArgumentException($"Expression '{propertyLambda}' refers to a method, not a property.");
    }

    PropertyInfo propInfo = expression.Member as PropertyInfo;

    if (propInfo == null)
    {
        throw new ArgumentException($"Expression '{propertyLambda}' refers to a field, not a property.");
    }

    if (type != propInfo.ReflectedType && !type.IsSubclassOf(propInfo.ReflectedType))
    {
        throw new ArgumentException($"Expression '{propertyLambda}' refers to a property that is not from type {type}.");
    }

    return propInfo;
}

Когда я передаю свойство примитивного типа функции, GetPropertyInfo завершается ошибкой, так как propertyLambda.Body as MemberExpression expression возвращает ноль.

Из Google этокажется, что причина этой проблемы в том, что я использую dynamic в качестве возвращаемого значения функции, где вместо этого должно быть что-то вроде TProperty.Вот ссылка Expression.Body, поскольку MemberExpression возвращает нулевое значение для свойства примитива

Однако я не уверен, как переписать мой метод Make для использования TProperty вместо dynamicкаждое свойство может иметь свой тип.

Вопрос Как передать несколько лямбда-выражений в метод Make и получить информацию о свойстве для каждого выражения?

1 Ответ

0 голосов
/ 04 марта 2019

Вам следует использовать object вместо dynamic в типах выражений.

public IEnumerable<Student> Make(IEnumerable<User> users, Expression<Func<User, object>> primaryProperty, params Expression<Func<User, object>>[] otherProperties)

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

var expressionBody = propertyLambda.Body;
if (expressionBody is UnaryExpression expression && expression.NodeType == ExpressionType.Convert)
{
    expressionBody = expression.Operand;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...