您好,
我在 C# 4.0 中使用 LINQ 和 EF。 我已将基本的 ELMAH 表拖到 EF 中(构建并保存了很多次)。 一切都按预期工作。
但我试图过于雄心勃勃,需要一点帮助 - 我正在尝试从作为变量传入的表达式中获取列名称。
我想要的是这个:
传入:x=>x.ErrorId
并得到:“ErrorId”
public void GetColumnName(Expression<Func<T, object>> property)
{
// The parameter passed in x=>x.Message
// Message works fine (probably because its a simple string) using:
string columnName = (property.Body as MemberExpression).Member.Name;
// But if I attempt to use the Guid or the date field then it
// is passed in as x => Convert(x.TimeUtc)
// As a result the above code generates a NullReference exception
// i.e. {"Object reference not set to an instance of an object."}
// What is the correct code here to extract the column name generically?
// Ideally in a way that won't bite me again in the future.
}
感谢您的帮助! 丹.
最佳答案
如果您还需要分解简单(或接近简单)的表达式,您将需要一些额外的工作来处理不同的情况。下面是一些处理一些常见情况的起始代码:
string GetColumnName<T,TResult>(Expression<Func<T,TResult>> property)
{
var member = GetMemberExpression(property.Body);
if (member == null)
throw new ArgumentException("Not reducible to a Member Access",
"property");
return member.Member.Name;
}
MemberExpression GetMemberExpression(Expression body)
{
var candidates = new Queue<Expression>();
candidates.Enqueue(body);
while (candidates.Count > 0)
{
var expr = candidates.Dequeue();
if (expr is MemberExpression)
{
return ((MemberExpression)expr);
}
else if (expr is UnaryExpression)
{
candidates.Enqueue(((UnaryExpression)expr).Operand);
}
else if (expr is BinaryExpression)
{
var binary = expr as BinaryExpression;
candidates.Enqueue(binary.Left);
candidates.Enqueue(binary.Right);
}
else if (expr is MethodCallExpression)
{
var method = expr as MethodCallExpression;
foreach (var argument in method.Arguments)
{
candidates.Enqueue(argument);
}
}
else if (expr is LambdaExpression)
{
candidates.Enqueue(((LambdaExpression)expr).Body);
}
}
return null;
}
产生如下输出:
GetColumnName((x) => x.X): "X"
GetColumnName((x) => x.X + 2): "X"
GetColumnName((x) => 2 + x.X): "X"
GetColumnName((x) => -x.X): "X"
GetColumnName((x) => Math.Sqrt(x.Y)): "Y"
GetColumnName((x) => Math.Sqrt(Math.Abs(x.Y))): "Y"
关于c# - LINQ 成员表达式获取列名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6269822/