我正在尝试使用表达式,以便对属性进行强类型化。
所以我有这个模型。
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属性,因为它是引用类型,但是它将为任何值类型返回null,在这种情况下,它返回的是ID(即int)。
那是为什么?解决方案是什么?
答案 0 :(得分:3)
Expression<Func<TEntity, object>>
是一个表达式,它构建一个函数,该函数返回一个object
(它是引用类型)。
如果将x => x.Id
作为该Expression的值传递,则由于int
是值类型,但Func希望返回引用类型,因此所得Func的返回类型将不匹配。
C#的编译器会看到这一点,并自动构建一个将int
包裹在object
内的Func(称为装箱)。但是该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");
}