繁体   English   中英

从 HttpResponseMessage 获取 object 并使用 MethodInfo.Invoke() 调用方法

[英]Get the object from HttpResponseMessage and invoke a method using MethodInfo.Invoke()

在记录 API 响应时,我需要过滤掉敏感数据。

我认为这应该在 LogRequestAndResponseHandler class 中完成。

这是我的代码:

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // This call is required to ensure that the logging is done against the current website credentials.
        ContextService.SetContextUserCredentials(Global.GlobalData.userCred);

        // let other handlers process the request
        var result = await base.SendAsync(request, cancellationToken);

        StreamContent contentStream = result.Content as StreamContent;

        
        // First branch for non-stream content
        if (result.Content != null && (contentStream == null))
        {
        
            // All models will inherit this interface
            var method = typeof(IGDPRSafeCloneable).GetMethod("SafeCloneForLogging");

            var responseBody = method.Invoke(result.Content.GetType(), null); // res == 20

            
            responseBody = JsonConvert.DeserializeObject(responseBody.ToString());

            Logger.DisplayDebug(LoggingLevel.Info, "INFO", "RESPONSE BODY: " + responseBody);
        }

这显然不起作用,但我需要更改var responseBody = method.Invoke(result.Content.GetType(), null);

但我坚持如何做到这一点。

这是 SafeCloneForLogging 方法在我的 model class 中的作用:

[DataContract]
public class SalesPerson : IGDPRSafeCloneable
{
    [DataMember(Name = "SalesmanId")]
    public int SalesmanId { get; set; }
    [DataMember(Name = "CarId")]
    public int CarId{ get; set; }
    [DataMember(Name = "SalesmanCode")]
    public string SalesmanCode { get; set; }
    [DataMember(Name = "Name")]
    public string Name { get; set; }

    public IGDPRSafeCloneable SafeCloneForLogging()
    {
        return new SalesPerson()
        {
            SalesmanId = SalesmanId,
            CarId= CarId,
            SalesmanCode = string.Empty,
            Name = string.Empty,
        };
    }
}

您的问题的根本症结在于您试图在没有类型的情况下执行基于类型的操作。 处理此问题的最简单方法是将类型传递给您可以反序列化的 SendAsync 方法,然后将其转换为IGDPRSafeCloneable 如果可转换,则调用SafeCloneForLogging方法并记录,如果不是 null。

public async Task<HttpResponseMessage> SendAsync<T>(HttpRequestMessage request, CancellationToken cancellationToken)
{
    // This call is required to ensure that the logging is done against the current website credentials.
    ContextService.SetContextUserCredentials(Global.GlobalData.userCred);

    // let other handlers process the request
    var result = await client.SendAsync(request, cancellationToken);

    StreamContent contentStream = result.Content as StreamContent;

    // First branch for non-stream content
    if (result.Content != null && (contentStream == null))
    {
        var responseBody = (
            (JsonConvert.DeserializeObject<T>(
                await result.Content.ReadAsStringAsync()
            ) as IGDPRSafeCloneable)?.SafeCloneForLogging());
        
        if (responseBody != null)
        {
            Logger.DisplayDebug(LoggingLevel.Info, "INFO", "RESPONSE BODY: " + responseBody);   
        }
    }
    
    return result;
}

但是,请注意,这里有一些明显的缺点。 您必须处理内容两次......一次记录它,然后再一次在SendAsync的调用者中。

根据您的记录器,最好在日志站点添加清理,特别是如果您的记录器可以处理对象并且您在记录期间序列化 object。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM