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

C#中替代Reflection实现动态字段映射的方案求助

高效映射Amounts列表到指定属性的替代方案

问题场景

我在C#类中定义了20个带JsonProperty特性的字符串属性(从LTRAMT1到LTRAMT20),需要根据请求体中amounts列表的position值,将对应value映射到对应属性。目前已实现LtrAmounts方法用于匹配position获取value,使用反射实现映射功能正常但响应时间过长;尝试用Dictionary实现时,响应会生成嵌套的LTRAMT父对象,不符合输出要求,寻求可行替代方案。

类属性示例:

[JsonProperty("LTR-AMT-1")]
public string? LTRAMT1 { get; set; }

// LTRAMT2至LTRAMT20定义类似

LtrAmounts方法代码:

public static string LtrAmounts(List<Amounts> amounts, int i)
{
    var filter = amounts.FirstOrDefault(x => x.position == i);
    return filter != null ? filter.value.ToString() : "";
}

请求体示例:

"amounts": [
    {"value": 0,"position": 1},
    {"value": 1624.96,"position": 2},
    {"value": 9901010,"position": 4},
    {"value": 35776,"position": 20}
]

可行替代方案

方案1:预编译表达式树构建赋值委托字典

通过表达式树预编译每个属性的赋值委托,初始化时构建一次position到委托的字典,后续赋值直接调用委托,性能接近硬编码赋值,同时兼顾代码维护性。

代码示例:

// 假设Amounts类结构
public class Amounts
{
    public decimal value { get; set; }
    public int position { get; set; }
}

public class TargetClass
{
    [JsonProperty("LTR-AMT-1")]
    public string? LTRAMT1 { get; set; }
    [JsonProperty("LTR-AMT-2")]
    public string? LTRAMT2 { get; set; }
    // ... 其余18个属性定义

    // 静态字典存储position到属性赋值委托
    private static readonly Dictionary<int, Action<TargetClass, string>> _positionSetters;

    static TargetClass()
    {
        _positionSetters = new Dictionary<int, Action<TargetClass, string>>();
        var type = typeof(TargetClass);

        for (int i = 1; i <= 20; i++)
        {
            var property = type.GetProperty($"LTRAMT{i}");
            if (property == null) continue;

            // 构建表达式树生成赋值委托
            var instanceParam = Expression.Parameter(typeof(TargetClass), "instance");
            var valueParam = Expression.Parameter(typeof(string), "value");
            var assignExpr = Expression.Assign(Expression.Property(instanceParam, property), valueParam);
            var setter = Expression.Lambda<Action<TargetClass, string>>(assignExpr, instanceParam, valueParam).Compile();

            _positionSetters.Add(i, setter);
        }
    }

    public void MapAmounts(List<Amounts> amounts)
    {
        // 先将amounts转为字典,将O(n)查找优化为O(1)
        var amountDict = amounts.ToDictionary(a => a.position, a => a.value.ToString());

        foreach (var kvp in _positionSetters)
        {
            kvp.Value(this, amountDict.TryGetValue(kvp.Key, out var val) ? val : "");
        }
    }
}

方案2:硬编码赋值逻辑(性能最优)

直接编写20个属性的赋值代码,完全避免反射或字典的额外开销,性能达到峰值,适合属性数量固定的场景。

代码示例:

public class TargetClass
{
    [JsonProperty("LTR-AMT-1")]
    public string? LTRAMT1 { get; set; }
    [JsonProperty("LTR-AMT-2")]
    public string? LTRAMT2 { get; set; }
    // ... 其余18个属性定义

    public void MapAmounts(List<Amounts> amounts)
    {
        var amountDict = amounts.ToDictionary(a => a.position, a => a.value.ToString());

        LTRAMT1 = amountDict.TryGetValue(1, out var val1) ? val1 : "";
        LTRAMT2 = amountDict.TryGetValue(2, out var val2) ? val2 : "";
        LTRAMT3 = amountDict.TryGetValue(3, out var val3) ? val3 : "";
        // ... 依次编写LTRAMT4至LTRAMT20的赋值逻辑
        LTRAMT20 = amountDict.TryGetValue(20, out var val20) ? val20 : "";
    }
}

方案3:优化查找逻辑+直接赋值

先将amounts列表转为Dictionary<int, decimal>,把原有的O(n)查找优化为O(1),再结合直接赋值,既解决反射性能问题,又避免字典导致的嵌套对象输出问题。

代码示例:

public void MapAmounts(List<Amounts> amounts)
{
    var amountDict = amounts.ToDictionary(a => a.position, a => a.value);

    LTRAMT1 = amountDict.ContainsKey(1) ? amountDict[1].ToString() : "";
    LTRAMT2 = amountDict.ContainsKey(2) ? amountDict[2].ToString() : "";
    // ... 其余属性同理赋值
    LTRAMT20 = amountDict.ContainsKey(20) ? amountDict[20].ToString() : "";
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:57:37