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

.NET Core中间件:如何替换含特定特性的属性值

在中间件中批量处理带IgnoreAttribute的属性/类

要实现这个需求,核心思路是在中间件中拦截请求/响应流,反序列化为通用对象后通过反射遍历处理带特性的成员,最后重新序列化写回流,具体步骤如下:

1. 中间件中拦截并复用请求/响应流

HttpContext的Request.Body和Response.Body默认是只能读取一次的流,所以需要先开启缓冲并复制到内存流,保证后续可以反复操作:

public class IgnoreAttributeMiddleware
{
    private readonly RequestDelegate _next;

    public IgnoreAttributeMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // 处理请求体
        context.Request.EnableBuffering();
        var requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
        context.Request.Body.Position = 0; // 重置流位置,留给后续中间件读取

        // 处理请求内容,替换带Ignore特性的字段
        var processedRequest = IgnoreAttributeProcessor.ProcessIgnoredProperties(requestBody);
        var modifiedRequestStream = new MemoryStream(Encoding.UTF8.GetBytes(processedRequest));
        context.Request.Body = modifiedRequestStream;

        // 处理响应体:替换原始响应流为可读写的内存流
        var originalResponseStream = context.Response.Body;
        using var responseBuffer = new MemoryStream();
        context.Response.Body = responseBuffer;

        // 调用后续中间件
        await _next(context);

        // 读取并处理响应内容
        responseBuffer.Position = 0;
        var responseBody = await new StreamReader(responseBuffer).ReadToEndAsync();
        var processedResponse = IgnoreAttributeProcessor.ProcessIgnoredProperties(responseBody);

        // 将处理后的响应写回原始流
        responseBuffer.Position = 0;
        await responseBuffer.CopyToAsync(originalResponseStream);
        context.Response.Body = originalResponseStream;
    }
}

2. 核心工具类:反射处理带特性的成员

写一个通用工具类,负责反序列化JSON、遍历对象成员检查IgnoreAttribute、替换为默认值,最后重新序列化:

using System.Reflection;
using System.Text.Json;

public static class IgnoreAttributeProcessor
{
    public static string ProcessIgnoredProperties(string json)
    {
        var obj = JsonSerializer.Deserialize<object>(json);
        if (obj == null) return json;

        var objType = obj.GetType();
        // 如果类本身标记了IgnoreAttribute,直接返回默认值的JSON
        if (objType.GetCustomAttribute<IgnoreAttribute>() != null)
        {
            var defaultValue = GetDefaultValue(objType);
            return JsonSerializer.Serialize(defaultValue);
        }

        RecursivelyProcessObject(obj);
        return JsonSerializer.Serialize(obj);
    }

    private static void RecursivelyProcessObject(object obj)
    {
        var type = obj.GetType();
        // 遍历所有公开实例属性
        foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            // 属性标记了IgnoreAttribute,设为默认值
            if (property.GetCustomAttribute<IgnoreAttribute>() != null)
            {
                property.SetValue(obj, GetDefaultValue(property.PropertyType));
                continue;
            }

            // 递归处理嵌套对象(排除值类型和字符串)
            var propertyValue = property.GetValue(obj);
            if (propertyValue == null || IsValueTypeOrString(property.PropertyType))
                continue;

            // 处理集合类型,遍历每个元素
            if (propertyValue is IEnumerable enumerable)
            {
                foreach (var item in enumerable)
                {
                    if (item != null)
                        RecursivelyProcessObject(item);
                }
            }
            else
            {
                RecursivelyProcessObject(propertyValue);
            }
        }
    }

    // 判断是否是值类型或字符串
    private static bool IsValueTypeOrString(Type type)
    {
        return type.IsValueType || type == typeof(string);
    }

    // 获取指定类型的默认值
    private static object GetDefaultValue(Type type)
    {
        return type.IsValueType ? Activator.CreateInstance(type) : null;
    }
}

3. 关键注意事项

  • 序列化配置兼容:如果项目用Newtonsoft.Json,把JsonSerializer替换为JsonConvert即可,核心逻辑不变。
  • 性能优化:反射遍历会有开销,高并发场景可以缓存类型的属性信息(比如预先记录哪些属性带IgnoreAttribute),避免每次重复反射。
  • 复杂类型处理:上述代码已支持嵌套对象和简单集合,若需处理字典、泛型集合等复杂类型,可在递归方法中添加对应分支。
  • 流操作规范:务必重置流的Position为0,否则后续中间件或框架无法正确读取流内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 11:36:07