C# Serilog访问LogEvent中传递给logging语句的原始对象

C# Serilog访问LogEvent中传递给logging语句的原始对象,c#,unity3d,serilog,C#,Unity3d,Serilog,我正在Unity3D中使用Serilog。 我有一个简单的接收器,它将Serilog日志语句写入Unity的Debug.LogFormat: public class UnityLogEventSink : ILogEventSink { public void Emit(LogEvent logEvent) { // QUESTION: How to pass a UnityEngine.Object to Serilog logging statement s

我正在Unity3D中使用Serilog。 我有一个简单的接收器,它将Serilog日志语句写入Unity的
Debug.LogFormat

public class UnityLogEventSink : ILogEventSink
{
    public void Emit(LogEvent logEvent)
    {
        // QUESTION: How to pass a UnityEngine.Object to Serilog logging statement such that it is available here?
        UnityEngine.Object contextObject = null;
            
        using (StringWriter stringBuffer = new StringWriter())
        {
            GetTextFormatter().Format(logEvent, stringBuffer);
            LogType logType = GetUnityLogType(logEvent);
            string logString = stringBuffer.ToString().Trim();
            Debug.LogFormat(logType, LogOption.NoStacktrace, contextObject, logString);
        }
    }
    
    // GetTextFormatter, GetUnityLogType etc. are defined here ...
}
现在我想将一个游戏对象传递给Serilog日志语句,这样我就可以在我的接收器中访问这个游戏对象。(使用GameObject调用
Debug.LogFormat
,当单击日志消息时,将在Unity编辑器中突出显示该对象。我希望如此。)

我试图用ScalarValue和自定义LogEventPropertyValue包装游戏对象,但游戏对象仍然转换为字符串(发生在Serilog的PropertyValueConverter.cs中)

我需要Debug.LogFormat的原始GameObject实例。 有没有办法保存游戏对象引用,这样我就可以在我的水槽中使用它

作为一种解决方法,我可以将引用存储在静态映射中,并使用映射的键记录字符串属性。通过这种方式,我可以稍后在接收器中从该映射获取实例。但这是围绕Serilog工作的。
是否有更好的解决方案利用Serilog?

Nick在年为我回答了这个问题

()

还可以创建特定于Unity的子类:

public class UnityObjectEnricher : ScalarValueEnricher
{
    public static readonly string unityObjectPropertyName = "unityObject";
    public UnityObjectEnricher(UnityEngine.Object value)
        : base(unityObjectPropertyName, value)
    {
    }
}

然后可以在接收器中访问此属性:

private UnityEngine.Object GetUnityEngineContextObject(LogEvent logEvent)
{
    if (logEvent.Properties.TryGetValue(UnityObjectEnricher.unityObjectPropertyName, out LogEventPropertyValue logEventPropertyValue))
    {
        if (logEventPropertyValue is ScalarValue scalarValue)
            return scalarValue.Value as UnityEngine.Object;
    }
    return null;
}

像这样使用它:

// Note: using LogContext requires Serilog configuration ".Enrich.FromLogContext()"
using (LogContext.Push(new UnityObjectEnricher(gameObject)))
{
    logger.Information("This is an info with context");
}
或:


你能提供一个答案吗?既然这发生在你正在使用的库的深处。。。看起来根本不可能。。。您输入的
对象值
在不同点被转换为
字符串
。。看起来这个库之后并没有提供参考…(旁白:这离一个不清楚的问题不远了),我重新表述了一些部分并添加了代码示例。希望现在更清楚。谢谢,ScalarValueEnricher是我需要的!我用新的Unity特定子类扩展了您的答案。
private UnityEngine.Object GetUnityEngineContextObject(LogEvent logEvent)
{
    if (logEvent.Properties.TryGetValue(UnityObjectEnricher.unityObjectPropertyName, out LogEventPropertyValue logEventPropertyValue))
    {
        if (logEventPropertyValue is ScalarValue scalarValue)
            return scalarValue.Value as UnityEngine.Object;
    }
    return null;
}
// Note: using LogContext requires Serilog configuration ".Enrich.FromLogContext()"
using (LogContext.Push(new UnityObjectEnricher(gameObject)))
{
    logger.Information("This is an info with context");
}
logger.ForContext(new UnityObjectEnricher(gameObject)).Information("This is another info with context");