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

C#如何实现自动匹配类属性值替换HTML对应占位符

C# 自动匹配对象属性替换HTML占位符实现方案

不需要手动逐行写Replace,核心用正则提取占位符+命名规则映射+递归反射取值实现,最终可以封装成和你预期一致的扩展方法直接调用。


核心实现步骤

  • 第一步:约定占位符和属性的映射规则
    你的占位符是蛇形命名(snake_case)、点分隔属性路径,C#类是帕斯卡命名(PascalCase),只需要写一个简单的字符串转换方法,把占位符的每一段路径转成C#属性对应的命名格式即可;如果有特殊命名不匹配的场景,可以加自定义特性做显式映射,灵活性更高。
  • 第二步:正则提取所有占位符
    用正则匹配所有被{}包裹的占位符内容,不需要提前预知HTML里有多少个占位符。
  • 第三步:递归反射按路径取值
    从根模型对象(你的Details实例)出发,按照拆分后的属性路径逐层查找对应属性值,路径中任意节点为空时直接返回空字符串,避免抛出空引用异常。
  • 第四步:批量替换所有占位符
    遍历所有提取到的占位符,拿到对应属性值后统一替换,最终返回处理完的HTML字符串。

可直接复用的代码实现

1. 命名格式转换辅助方法

using System.Reflection;
using System.Text.RegularExpressions;

// 蛇形命名转帕斯卡命名 例如 created_at -> CreatedAt, line_1 -> Line1
private static string SnakeCaseToPascal(string snakeCaseStr)
{
    if (string.IsNullOrWhiteSpace(snakeCaseStr)) return string.Empty;
    var segments = snakeCaseStr.Split('_', StringSplitOptions.RemoveEmptyEntries);
    for (int i = 0; i < segments.Length; i++)
    {
        segments[i] = char.ToUpper(segments[i][0]) + segments[i][1..].ToLower();
    }
    return string.Concat(segments);
}

2. 递归按属性路径取值方法

private static object? GetValueByPropertyPath(object rootObj, string[] pathSegments, int currentIndex = 0)
{
    if (rootObj == null || currentIndex >= pathSegments.Length) return rootObj;
    
    var currentPropName = SnakeCaseToPascal(pathSegments[currentIndex]);
    // 适配特殊命名:当前占位符customer_info对应Customer属性,可按需扩展,也可通过自定义特性实现映射
    if (currentPropName == "CustomerInfo") currentPropName = "Customer";
    
    var prop = rootObj.GetType().GetProperty(currentPropName, BindingFlags.Public | BindingFlags.Instance);
    if (prop == null) return string.Empty; // 找不到对应属性返回空,不抛异常中断流程
    
    var nextObj = prop.GetValue(rootObj);
    return GetValueByPropertyPath(nextObj, pathSegments, currentIndex + 1);
}

3. 封装字符串扩展方法,匹配预期调用形式

public static class StringTemplateExtensions
{
    // 预编译正则匹配所有{xxx}格式的占位符
    private static readonly Regex PlaceholderRegex = new Regex(@"\{([^{}]+)\}", RegexOptions.Compiled);
    
    public static string ReplaceWithModelProperties(this string template, object model)
    {
        if (string.IsNullOrWhiteSpace(template) || model == null) return template;
        
        return PlaceholderRegex.Replace(template, match =>
        {
            var placeholderPath = match.Groups[1].Value.Trim();
            var pathSegments = placeholderPath.Split('.', StringSplitOptions.RemoveEmptyEntries);
            var propValue = GetValueByPropertyPath(model, pathSegments);
            // 若属性值是用户输入内容,建议替换为HttpUtility.HtmlEncode(propValue)做安全转义,避免XSS
            return propValue?.ToString() ?? string.Empty;
        });
    }
}

使用方式

直接调用扩展方法即可,不需要手写任何Replace逻辑:

public static string ReplaceStringPlaceHolders(Details details)
{
    string myHtml = File.ReadAllText(@"...Path");
    // 一行完成所有占位符替换
    return myHtml.ReplaceWithModelProperties(details);
}

优化建议

  • 性能优化:如果方法调用频率很高,可以把反射拿到的PropertyInfo按类型+属性名缓存起来,避免每次匹配都重新反射查找属性,性能可提升一个数量级。
  • 灵活适配:对于特殊的占位符与属性名映射关系,可以自定义[PlaceholderName("xxx")]特性打在对应属性上,反射时优先读取特性配置的名称做匹配,不需要硬编码映射规则。
  • 空值兜底:可以给需要默认值的属性加默认值特性,当属性值为空时自动展示预设默认内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:45:35