是否可以基于开放泛型对serilog事件数据进行解构?例如,我正在尝试这样做:
.Destructure.ByTransforming<CosmosResponse<T>>(
transform =>
new
{
transform.StatusCode,
transform.RequestCharge,
transform.ActivityId,
})
这样我就可以获取任何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,尽管:
当解构对象时,转换指定类型的实例
如果谓词返回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
上存在的属性亮起)