C# 转换表达式<;Func<;TClass,TField>&燃气轮机;表达<;Func<;TClass,object>&燃气轮机;

C# 转换表达式<;Func<;TClass,TField>&燃气轮机;表达<;Func<;TClass,object>&燃气轮机;,c#,C#,我正在尝试创建一个通用的“更新表达式生成器”——一个可以传递的对象,用于指示需要为哪些字段指定什么值。 我所做的是: public class UpdateExpression<TClass> : Dictionary<Expression<Func<TClass, object>>, object> {}; public class UpdateExpressionBuilder<TClass> { private Up

我正在尝试创建一个通用的“更新表达式生成器”——一个可以传递的对象,用于指示需要为哪些字段指定什么值。 我所做的是:

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;
    }
}
我尝试添加约束
where-TField:class,new()
但这并没有改变任何事情

更改“添加到”的签名时
Add(表达式字段、对象值)

它工作得很好。然而,随后我放松了编译时类型检查,因此
Add(p=>p.FirstName,123)
将编译,但在运行时失败。

我完全同意Daisy在其注释中写的内容。。。你还是要求一些东西:

public UpdateExpressionBuilder<TClass> Add<TField>(Expression<Func<TClass, TField>> field, TField value)
{
    var body = field.Body;

    // Boxing for value types
    if (typeof(TField).IsValueType)
    {
        body = Expression.Convert(body, typeof(object));
    }

    Expression<Func<TClass, object>> field2 = Expression.Lambda<Func<TClass, object>>(body, field.Parameters);

    fieldsValues.Add(field2, value);
    return this;
}
public UpdateExpressionBuilder添加(表达式字段,TField值)
{
var body=field.body;
//值类型的装箱
if(typeof(TField).IsValueType)
{
body=Expression.Convert(body,typeof(object));
}
Expression field2=Expression.Lambda(body,field.Parameters);
字段值。添加(字段2,值);
归还这个;
}
然后

var personUpdateExpression = new UpdateExpressionBuilder<Person>()
    .Add(p => p.FirstName, "David")
    .Add(p => p.MiddleName, "A")
    .Add(p => p.Age, 30)
    .Build();
var personUpdateExpression=new UpdateExpressionBuilder()
.Add(p=>p.FirstName,“David”)
.Add(p=>p.MiddleName,“A”)
.Add(p=>p.年龄,30岁)
.Build();
请注意,您的示例仅为字符串,但我为
int
添加了一个示例


最后,我们重写了
表达式
。对于引用类型,除了更改
Func
的返回类型外,无需执行任何操作。对于值类型,您需要显式装箱。

编辑问题标题可能是值得的-您不是在转换委托,而是在转换表达式树。这有点不同。此外,还不清楚如何处理生成的表达式树。我怀疑您会发现不需要
Func
,因为您需要转换回正确的字段类型。也许您应该只存储一个
列表
?(此外,您还需要将表达式树转换为一个值来设置值。这可能是可行的,但在继续之前,我会确保它适用于您打算执行的操作。)谢谢。有关此选项的用法,请参阅:
public UpdateExpressionBuilder<TClass> Add<TField>(Expression<Func<TClass, TField>> field, TField value)
{
    var body = field.Body;

    // Boxing for value types
    if (typeof(TField).IsValueType)
    {
        body = Expression.Convert(body, typeof(object));
    }

    Expression<Func<TClass, object>> field2 = Expression.Lambda<Func<TClass, object>>(body, field.Parameters);

    fieldsValues.Add(field2, value);
    return this;
}
var personUpdateExpression = new UpdateExpressionBuilder<Person>()
    .Add(p => p.FirstName, "David")
    .Add(p => p.MiddleName, "A")
    .Add(p => p.Age, 30)
    .Build();