Использование выражений для получения поддержки intellisense в C # - PullRequest
0 голосов
/ 09 ноября 2018

Я пытаюсь использовать выражения для строгой типизации над свойствами.

Итак, у меня есть эта модель.

public class Entity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

И этот метод, который, в конце концов, мне бы хотелось каким-то образом использовать свойства, но сейчас я просто хочу их вернуть.

public List<string> DoSomething<TEntity>(params Expression<Func<TEntity, object>>[] expressions)
{  
        List<string> props = new List<string>();

        foreach (var expression in expressions)
        {
            var memberExpression = expression.Body as MemberExpression;

            var q = memberExpression.Member.Name;

            props.Add(q);
        }
        return props;
}

Это использование

var props = DoSomething<Entity>(x => x.Id, x => x.Name);

Ну, это работает, но только частично. Под этим я подразумеваю, что он будет работать для ссылочных типов, например, он будет работать для свойства Name, потому что это ссылочный тип, но он будет возвращать ноль для любого типа значения, в данном случае для ID, который является целым числом.

Почему это так и каково решение?

1 Ответ

0 голосов
/ 09 ноября 2018

Expression<Func<TEntity, object>> - это выражение, которое создает Func, который возвращает object (который является ссылочным типом). Если вы передадите x => x.Id в качестве значения этого выражения, возвращаемый тип полученного Func не будет совпадать, так как int является типом значения, но ожидается, что Func возвратит ссылочный тип.

Компилятор C # увидит это и автоматически создаст Func, который обернет int в object (называемый боксом). Но этот Func больше не имеет простого MemberExpression в качестве своего тела, потому что MemberExpression должен быть заключен в «боксерское выражение».

Это в основном то, что происходит. Таким образом, вы должны обработать случай, когда expression.Body не относится к типу MemberExpression, чтобы это исправить.

Это не проверено, но это может помочь:

if (!(expression.Body is MemberExpression))
{
    if (expression.Body is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.TypeAs)
        expression = unaryExpression.Operand as MemberExpression;
    else
        expression = null;
    if (expression == null)
        throw new ArgumentException("something happened");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...