gpt4 book ai didi

c# - 具有异步/等待的 ContextBoundObject

转载 作者:太空狗 更新时间:2023-10-29 23:51:23 25 4
gpt4 key购买 nike

我有一个使用 AOP 和 ContextBoundObject 的系统。

这用于拦截方法调用并在函数前后执行某些操作。一切正常,直到我将“要拦截的函数”设为异步。

我知道 C# 编译器将异步方法重写为状态机,一旦达到“等待”状态,状态机就会将控制权返回给接收器因此它继续进入拦截并执行本应仅在方法之后执行的代码。

我可以看到 IMessageSink 中有一个“AsyncProcessMessage”,但我找不到调用它的方法,我不确定它是否适用于 async/await 场景。

有没有办法让 Async/Await 与 ContextBoundObject 一起工作?使用另一种面向方面的编程方法是这里唯一的选择吗?

下面的代码示例具有使用“Audit”属性修饰并放置在作为 ContextBoundObject 的 AuditFacade 中的要拦截的方法。 AuditSink 中的 SyncProcessMessage 方法具有方法前后执行的逻辑。

 [AuditBoundary]
public class AuditFacade : ContextBoundObject
{
[Audit]
public ResponseObject DoSomthing()
{
//Do something
return new ResponseObject();
}

/// <summary>
/// Async Method to be intercepted
/// </summary>
/// <returns></returns>
[Audit]
public async Task<ResponseObject> DoSomthingAysnc()
{
//Do something Async
await Task.Delay(10000);
return new ResponseObject();
}
}

[AttributeUsage(AttributeTargets.Method)]
public class AuditAttribute : Attribute
{
}

[AttributeUsage(AttributeTargets.Class)]
public class AuditBoundaryAttribute : ContextAttribute
{
public AuditBoundaryAttribute()
: base("AuditBoundary" + Guid.NewGuid().ToString())
{
}
public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
{
ctorMsg.ContextProperties.Add(new AuditProperty());
}
}

public class AuditProperty : IContextProperty, IContributeObjectSink
{
public string Name
{
get { return "AuditProperty"; }
}

public bool IsNewContextOK(Context newCtx)
{
var p = newCtx.GetProperty("AuditProperty") as AuditProperty;

if (p == null)
return false;

return true;
}

public void Freeze(Context newContext)
{
}

public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
{
return new AuditSink(nextSink);
}

}

public class AuditSink : IMessageSink
{
private IMessageSink nextSink;

public AuditSink(IMessageSink nextSink)
{
this.nextSink = nextSink;
}

public IMessage SyncProcessMessage(IMessage msg)
{
var message = msg as IMethodCallMessage;

IMethodReturnMessage returnMessage = null;
ResponseObject response;

//Some Pre Processing happens here
var newMessage = new MethodCallMessageWrapper(message);

//Invoke the Method to be Audited
returnMessage = nextSink.SyncProcessMessage(newMessage) as IMethodReturnMessage;
response = returnMessage.ReturnValue as ResponseObject;

//Some Post Processing happens here with the "response"
return returnMessage;
}

public IMessageSink NextSink
{
get { return this.nextSink; }
}
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
return nextSink.AsyncProcessMessage(msg, replySink);
}
}

最佳答案

我对ContextBoundObject一无所知,但我认为AsyncProcessMessage()async-无关await 并且以下内容应该使用正常的 SyncProcessMessage() 工作:

  1. 执行预处理步骤。
  2. 调用异步方法。
  3. 使用 ContinueWith()await 将您的后处理步骤作为返回的 Task 的延续。
  4. 将延续 Task 返回给调用者。

如果您同意在线程池上执行后处理,那么 ContinueWith() 可能更简单。如果您需要在原始上下文中执行后处理,请使用 await

await 版本可能如下所示:

var responseTask = (Task<ResponseObject>)returnMessage.ReturnValue;

Func<Task<ResponseObject>> postProcessTaskFunc = async () =>
{
var response = await responseTask;
// Some Post Processing happens here with the "response"
return response;
}

return new ReturnMessage(postProcessTaskFunc(), …);

关于c# - 具有异步/等待的 ContextBoundObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20256030/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com