用serilog破解开放式仿制药

问题描述 投票:4回答:1

是否有可能基于开放式通用结构来描述serilog事件数据?例如,我正在尝试这样做:

.Destructure.ByTransforming<CosmosResponse<T>>(
    transform =>
        new
        {
            transform.StatusCode,
            transform.RequestCharge,
            transform.ActivityId,
        })

这样我就可以获取任何Cosmos响应对象并仅提取应记录的特定信息位。但是,它似乎不起作用 - 我的回调永远不会被调用。

我也尝试过调用ByTransformingWhere并且总是返回true。我很惊讶地看到每个日志调用都需要它,而不仅仅是那些处理CosmosResponse<T>的日志。虽然它确实为Cosmos响应对象调用了我的谓词,但它仍然没有调用回调来转换对象。

Update

这是迄今为止我能够取得的最好成绩:

.Destructure.ByTransformingWhere<dynamic>(
    t => t.IsGenericType && t.GenericTypeArguments.Length == 1 && t.IsSubclassOf(typeof(CosmosResponse<>).MakeGenericType(t.GenericTypeArguments[0])),
    r =>
        new
        {
            r.StatusCode,
            r.RequestCharge,
            r.ActivityId
        })

这有点令人担心,因为每个日志调用都会调用谓词,但我找不到任何其他方法。

Update 2

在这种情况下,更好的方法是完全避免解构,而是向Cosmos客户端添加自定义处理程序。这有助于拦截所有请求,我关注的各种信息(状态代码,请求费用等)都存在于响应头中。

当然,这是特定于Cosmos DB的客户端库,并且没有说明原始问题。如果您确实需要基于开放式泛型类型进行解构,则上述仍然是最知名的选项。

c# generics serilog
1个回答
4
投票

我期待这样的事情可以完成这项工作:

.Destructure.ByTransformingWhere<dynamic>(
                    t => t.GetGenericTypeDefinition() == typeof(CosmosResponse<>),
                    o => new { o.Whatever })

但是,作为docs say

解构对象时,如果谓词返回true,则使用提供的函数转换指定类型的实例。小心避免谓词中的任何密集工作,因为它可以显着减慢管道。

因此,了解如何优化或避免反射调用可能是一个好主意。

UPDATE

要进行适当的智能感知/类型检查,您应该能够:

.Destructure.ByTransformingWhere<CosmosResponse<object>>(
    t => t.IsGenericType && t.GenericTypeArguments.Length == 1 && t.IsSubclassOf(typeof(CosmosResponse<>).MakeGenericType(t.GenericTypeArguments[0])),
    r =>
        new
        {
            r.StatusCode,
            r.RequestCharge,
            r.ActivityId
        })

(即提供CosmosResponse<object>作为类型参数而不是dynamic,以便CosmosResponse上存在的属性亮起)

© www.soinside.com 2019 - 2024. All rights reserved.