为了记录每个 Actor 操作的自定义数据,您可以使用以下方法:
protected override Task OnPreActorMethodAsync(ActorMethodContext c)
protected override Task OnPostActorMethodAsync(ActorMethodContext c)
为了获取调用上下文,我发现 CallContext.LogicalGetData 在这种情况下不起作用。幸运的是,演员本身确实了解其背景。您可以使用一些反射来获得它。
例如:
protected override Task OnPreActorMethodAsync(ActorMethodContext c)
{
var correlationID = this.GetActorContext() ?? Guid.Empty.ToString("N");
string message = $"Actor method is being invoked. Method name: {c.MethodName}, actor type: {GetType().FullName}, actor ID: {Id}, CorrelationID:{correlationID}";
ActorEventSource.Current.ActorMessage(this, message);
return Task.FromResult(true);
}
protected override Task OnPostActorMethodAsync(ActorMethodContext c)
{
var correlationID = this.GetActorContext() ?? Guid.Empty.ToString("N");
string message = $"Actor method has completed. Method name: {c.MethodName}, actor type: {GetType().FullName}, actor ID: {Id}, CorrelationID:{correlationID}";
ActorEventSource.Current.ActorMessage(this, message);
return Task.FromResult(true);
}
结合:
public static class ActorContextExtensions
{
public static string GetActorContext(this Actor actor)
{
var concurrencyLockProperty = GetPropertyInfo("ConcurrencyLock", typeof(ActorBase));
var concurrencyLockPropertyValue = concurrencyLockProperty.GetValue(actor);
var currentContextProperty = GetPropertyInfo("Test_CurrentContext", concurrencyLockPropertyValue.GetType());
string currentContextPropertyValue = (string)currentContextProperty.GetValue(concurrencyLockPropertyValue);
return currentContextPropertyValue;
}
private static PropertyInfo GetPropertyInfo(string propertyName, IReflect owner)
{
var property = owner.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance);
if (property == null) throw new InvalidOperationException($"Failed to find property '{propertyName}' on '{owner}'.");
return property;
}
}
这样做的明显缺点是,只要 ActorBase 的内部发生变化,您就需要相应地更改反射代码。