使用 serilog 解构开放泛型
Destructuring open generics with 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。
我期待像这样的东西可以完成这项工作:
.Destructure.ByTransformingWhere<dynamic>(
t => t.GetGenericTypeDefinition() == typeof(CosmosResponse<>),
o => new { o.Whatever })
作为 docs say,不过:
When destructuring objects, transform instances of the specified type
with the provided function, if the predicate returns true. Be careful
to avoid any intensive work in the predicate, as it can slow down the
pipeline significantly.
因此,了解如何优化或避免这些反射调用可能是个好主意。
更新
要进行正确的智能感知/类型检查,您应该能够做到:
.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
上存在的属性亮起)
是否可以基于开放通用来解构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。
我期待像这样的东西可以完成这项工作:
.Destructure.ByTransformingWhere<dynamic>(
t => t.GetGenericTypeDefinition() == typeof(CosmosResponse<>),
o => new { o.Whatever })
作为 docs say,不过:
When destructuring objects, transform instances of the specified type with the provided function, if the predicate returns true. Be careful to avoid any intensive work in the predicate, as it can slow down the pipeline significantly.
因此,了解如何优化或避免这些反射调用可能是个好主意。
更新
要进行正确的智能感知/类型检查,您应该能够做到:
.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
上存在的属性亮起)