为了解决这个问题,我放弃了使用 Trace.CorrelationManager 属性。作为这些属性的替代品,我现在使用添加到扩展类的自定义属性。我现在可以直接修改此扩展上的 ActivityId 和 LogicalOperationStack,可以在任何操作请求的生命周期内访问它们,这与使用 Trace.CorrelationManager 属性一样方便。
另外,我可以存储我想在请求的生命周期中使用的任何其他自定义属性。一个很好的例子是客户 ID 或资源 ID,它也可以用于日志记录以获得更好的可支持性。
using System;
using System.Collections;
using System.ServiceModel;
namespace MyNamespace
{
/// <summary>
/// Class that represents an extension used to store custom data for the life of a WCF OperationContext.
/// </summary>
public class OperationContextExtension : IExtension<OperationContext>
{
/// <summary>The activity id of the operation.</summary>
private Guid activityId;
/// <summary>The logical operation stack of the operation.</summary>
private Stack logicalOperationStack;
/// <summary>
/// Initializes a new instance of the OperationContextExtension class.
/// </summary>
public OperationContextExtension()
{
this.logicalOperationStack = new Stack();
}
/// <summary>
/// Gets the current OperationContextExtension extension from the OperationContext.
/// </summary>
public static OperationContextExtension Current
{
get
{
OperationContextExtension context;
if (OperationContext.Current == null)
{
context = null;
}
else
{
context = OperationContext.Current.Extensions.Find<OperationContextExtension>();
}
return context;
}
}
/// <summary>
/// Gets or sets the activity id for the current operation.
/// </summary>
public Guid ActivityId
{
get { return this.activityId; }
set { this.activityId = value; }
}
/// <summary>
/// Gets the LogicalOperationStack for the current operation.
/// </summary>
public Stack LogicalOperationStack
{
get { return this.logicalOperationStack; }
}
/// <summary>
/// Enables an extension object to find out when it has been aggregated. Called when the extension is added
/// to the System.ServiceModel.IExtensibleObject Extensions property.
/// </summary>
/// <param name="owner">The extensible object that aggregates this extension.</param>
public void Attach(OperationContext owner)
{
// Use this method for request initialization if needed
}
/// <summary>
/// Enables an object to find out when it is no longer aggregated. Called when an extension is removed
/// from the System.ServiceModel.IExtensibleObject Extensions property.
/// </summary>
/// <param name="owner">The extensible object that aggregates this extension.</param>
public void Detach(OperationContext owner)
{
// Use this method for request cleanup if needed
}
}
}
您现在需要将此扩展添加到 OperationContext。首先,您需要找到适合 WCF 行为扩展的挂钩。一个流行的选项是使用应用于 IEndpointBehavior 的 MessageInspector。这里有一些关于如何实现这一点的精彩读物(如果我的没有帮助,快速搜索将产生许多有用的例子):
一旦你有了你的钩子,你想尽快将你的扩展添加到 OperationContext 中,使用以下行:
// Add an extension object to the current operation context to track custom state across all threads
// for the life of the operation
OperationContext.Current.Extensions.Add(new OperationContextExtension());
现在,您几乎可以从代码工作流中的任何位置访问您的 ActivityId 属性和 LogicalOperationStack,或您在此类中定义的任何其他属性:
LogOperation(OperationContextExtension.Current.ActivityId, logMessage);
OperationContextExtension.Current.LogicalOperationStack.Push("Starting 'Nested Activity' 3...");
希望这可以帮助!
-穆罕默德