【发布时间】:2018-07-01 11:19:07
【问题描述】:
我正在尝试创建一个通用的“更新表达式构建器”——一个可以传递的对象,用于指示需要为哪些字段分配什么值。 我所做的是:
public class UpdateExpression<TClass> : Dictionary<Expression<Func<TClass, object>>, object>
{};
public class UpdateExpressionBuilder<TClass>
{
private UpdateExpression<TClass> fieldsValues;
public UpdateExpressionBuilder()
{
fieldsValues = new UpdateExpression<TClass>();
}
public UpdateExpressionBuilder<TClass> Add<TField>(Expression<Func<TClass, TField>> field, TField value)
{
fieldsValues.Add(field, value);
return this;
}
public UpdateExpression<TClass> Build()
{
return fieldsValues;
}
}
这意味着用作:
var personUpdateExpression = new UpdateExpressionBuilder<Person>()
.Add(p => p.FirstName, "David")
.Add(p => p.MiddleName, "A")
.Build();
然后我可以将 personUpdateExpression 作为参数发送给任何方法,例如数据库更新。
问题是调用fieldsValues.Add(field, value)
不编译。错误是:
error CS1503: Argument 1: cannot convert from
'System.Linq.Expressions.Expression<System.Func<TClass, TField>>' to
'System.Linq.Expressions.Expression<System.Func<TClass, object>>'
我尝试添加约束where TField : class, new()
但这并没有改变任何东西。
更改 Add to 的签名时
Add(Expression<Func<TClass, object>> field, object value)
它完美地工作。但是后来我放松了编译时类型检查,所以Add(p => p.FirstName, 123) 将编译,但在运行时失败。
【问题讨论】:
-
可能值得编辑您的问题标题 - 您不是在转换代表,而是在转换表达式树。这有点不同。此外,不清楚您实际上会对生成的表达式树做什么。我怀疑您会发现您不想要
Func<TClass, object>,因为您需要转换回正确的字段类型。也许您应该只存储List<Expression>? -
(此外,您需要将表达式树转换为 fetch 一个值到 set 一个值。这可能是可行,但我会确保它适用于您打算做的事情,然后再进一步。)
标签: c#