使用serilog破坏开放的泛型

时间:2019-02-19 23:02:21

标签: c# generics serilog

是否有可能基于开放的泛型对serilog事件数据进行解构?例如,我正在尝试这样做:

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

因此,我可以采用 any Cosmos响应对象,并仅提取应记录的特定信息位。但是,它似乎不起作用-从未调用过我的回调。

我还尝试调用ByTransformingWhere,并且总是返回true。我很惊讶地看到它被称为每个记录调用,而不仅仅是那些处理CosmosResponse<T>的对象。而且,尽管它确实调用了Cosmos响应对象的谓词,但仍然没有调用回调来转换对象。

更新

这是到目前为止我能达到的最好成绩:

.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
        })

这有点令人担忧,因为谓词被称为个日志调用,但是我找不到其他解决方法。

更新2

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

当然,这是特定于Cosmos DB的客户端库,对于原始问题没有任何说明。如果您实际上确实需要基于开放的泛型类型进行结构分解,那么上述仍然是最著名的选择afaik。

1 个答案:

答案 0 :(得分:4)

我希望这样的事情可以完成:

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

尽管是docs say

  

解构对象时,转换指定类型的实例   如果谓词返回true,则使用提供的函数。小心   避免在谓词中进行任何繁重的工作,因为这会减慢谓词的速度   大量流水线。

因此,最好看看如何优化或避免那些反射调用。

更新

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

.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上存在的属性亮起)

相关问题