#c# #reflection #linq-expressions
#c# #отражение #linq-выражения
Вопрос:
У меня есть класс, который выглядит следующим образом:
public class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
}
Мне нужно сделать это:
var memberExpressions = ConvertToMemberExpressions<MyClass>(o => o.Id, o => o.Name);
...
public static List<MemberExpression> ConvertToMemberExpressions<T>(params Expression<Func<T, object>>[] methodExpressions)
{
var results = new List<MemberExpression>();
foreach(var methodExpression in methodExpressions)
{
var memberExpression = methodExpression.Body as MemberExpression;
results.Add(memberExpression);
}
return results;
}
Проблема в том, что из-за Func<T, object>
(чтобы иметь возможность включать оба int
параметра и string
в качестве параметров) мое MethodExpression выглядит так: {o => Convert(o.Id, Object)}
, что мне не нужно. Мне нужно достичь o.Id
.
Этого не происходит со строками: {o => o.Name}
, здесь нет преобразования.
Я использую Func<T,object>
, чтобы иметь возможность использовать Intellisense и получать доступ к реквизитам MyClass. Я пытался использовать Func<T, dynamic>
вместо этого, но результат тот же.
Это можно решить с помощью нескольких перегрузок:
public static ConvertToMemberExpressions<TClass, T1>(Expression<Func<TClass,T1>>[] methodExpression1)
public static ConvertToMemberExpressions<TClass, T1, T2>(Expression<Func<TClass,T1>>[] methodExpression1, Expression<Func<TClass,T2>>[] methodExpression2)
...
…но это жертва, которой я хотел бы избежать, если это возможно.
Вопрос:
Возможно ли построить o => o.Id
из o => Convert(o.Id, Object)
?
Ответ №1:
Просто проверьте, является ли ваш methodExpression.Body
a UnaryExpression
с a NodeType
из Convert
:
public static List<MemberExpression> ConvertToMemberExpressions<T>(params Expression<Func<T, object>>[] methodExpressions)
{
var results = new List<MemberExpression>();
foreach (var methodExpression in methodExpressions)
{
var expr = methodExpression.Body;
if (expr is UnaryExpression unaryExpression amp;amp; unaryExpression.NodeType == ExpressionType.Convert)
{
expr = unaryExpression.Operand;
}
if (expr is MemberExpression memberExpression)
{
results.Add(memberExpression);
}
else
{
throw new ArgumentException($"Unexpected expression type {expr.NodeType}");
}
}
return results;
}
При работе с выражениями отладчик — ваш друг:
Комментарии:
1. Большое спасибо, это кажется правильным решением. Я, вероятно, слишком много думал об этом …
unaryExpression.Operand
все время был у меня перед глазами, но я думал, что не смогу использовать его как MemberExpression, поди разберись. Еще раз спасибо.