You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何定义可接收赋值语句为参数的函数?代码重构场景

解决思路:用表达式树实现兼具赋值与添加Field的扩展方法

首先得明确:你想要的AllFields.Add(SomeProperty = new IntField(){...})写法直接用会有编译问题——因为SomeProperty是int类型,赋值表达式的结果是int(左操作数的类型),而你的AllFields是IList<IField>,没法把int实例加到列表里。我们可以用表达式树绕开这个限制,同时保留接近你想要的简洁语法。

步骤1:完善Field类与接口

先确保你的IntField、DecimalField实现了IField,并且支持隐式转换到对应的数值类型(这样赋值给int/decimal属性时不用显式强转):

public interface IField
{
    string ColumnName { get; set; }
    string DisplayName { get; set; }
    bool IsEditable { get; set; }
    bool IsRequired { get; set; }
}

public class IntField : IField
{
    public string ColumnName { get; set; }
    public string DisplayName { get; set; }
    public bool IsEditable { get; set; }
    public bool IsRequired { get; set; }
    public int Value { get; set; }

    // 隐式转换为int,让赋值语句能正常编译
    public static implicit operator int(IntField field) => field.Value;
}

public class DecimalField : IField
{
    public string ColumnName { get; set; }
    public string DisplayName { get; set; }
    public bool IsEditable { get; set; }
    public bool IsRequired { get; set; }
    public decimal Value { get; set; }

    // 隐式转换为decimal
    public static implicit operator decimal(DecimalField field) => field.Value;
}

步骤2:编写扩展方法

我们用泛型表达式树作为参数,解析赋值语句,既执行属性赋值,又把Field对象加到列表:

public static class Extensions
{
    public static void Add<TField>(this IList<IField> source, Expression<Func<TField>> assignmentExpression)
        where TField : IField
    {
        // 检查表达式是否是赋值操作
        if (assignmentExpression.Body is not AssignmentExpression assignment)
        {
            throw new ArgumentException("参数必须是属性/字段的赋值表达式", nameof(assignmentExpression));
        }

        // 编译并执行赋值,给目标属性赋值
        var assignFunc = assignmentExpression.Compile();
        var fieldInstance = assignFunc();

        // 将Field对象添加到列表
        source.Add(fieldInstance);
    }
}

步骤3:调用方式

只需要用() =>把赋值语句包裹起来,就能同时完成属性赋值和Field添加:

IList<IField> AllFields = new List<IField>();
int SomeProperty;
decimal SomeProperty2;

// 给int属性赋值,同时把IntField加到列表
AllFields.Add(() => SomeProperty = new IntField 
{ 
    ColumnName = "SomeProperty", 
    DisplayName = "Some Property", 
    IsEditable = false, 
    IsRequired = true,
    Value = 100 // 设置Field的数值
});

// 给decimal属性赋值,同时把DecimalField加到列表
AllFields.Add(() => SomeProperty2 = new DecimalField 
{ 
    ColumnName = "SomeProperty2", 
    DisplayName = "Some Property 2", 
    IsEditable = true, 
    IsRequired = false,
    Value = 99.99m
});

为什么这个方案可行?

表达式树让我们能获取到赋值语句右边的Field对象实例(即使左边是数值类型),同时编译执行表达式完成属性赋值。虽然比你最初设想的写法多了() =>包裹,但已经是最接近你需求的简洁实现了。

内容的提问来源于stack exchange,提问作者Eminem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:51:19