Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有异步/等待的ContextBoundObject_C#_.net_Asynchronous_Aop_Async Await - Fatal编程技术网

C# 具有异步/等待的ContextBoundObject

C# 具有异步/等待的ContextBoundObject,c#,.net,asynchronous,aop,async-await,C#,.net,Asynchronous,Aop,Async Await,我有一个使用AOP和ContextBoundObject的系统 这用于拦截方法调用并在函数前后执行某些操作。在我将“要拦截的函数”设置为异步之前,一切都正常 我知道C#编译器会将异步方法重写到状态机中,一旦到达“wait”,状态机就会将控制权返回到接收器 因此,它将继续执行拦截并执行代码,该代码将仅在方法之后执行 我可以看到在IMessageSink中有一个“AsyncProcessMessage”,但我找不到调用它的方法,而且我不确定它是否能在异步/等待场景中工作 有没有办法让Async/Aw

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

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

我知道C#编译器会将异步方法重写到状态机中,一旦到达“wait”,状态机就会将控制权返回到接收器 因此,它将继续执行拦截并执行代码,该代码将仅在方法之后执行

我可以看到在IMessageSink中有一个“AsyncProcessMessage”,但我找不到调用它的方法,而且我不确定它是否能在异步/等待场景中工作

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

下面的代码示例使用“Audit”属性修饰要拦截的方法,并将其放置在AuditFacade中,AuditFacade是ContextBoundObject。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);
    }
}
[AuditBoundary]
公共类AuditFacade:ContextBoundObject
{
[审计]
公共响应对象DoSomthing()
{
//做点什么
返回新的ResponseObject();
}
/// 
///要拦截的异步方法
/// 
/// 
[审计]
公共异步任务DoSomthingAysnc()
{
//做一些异步的事情
等待任务。延迟(10000);
返回新的ResponseObject();
}
}
[AttributeUsage(AttributeTargets.Method)]
公共类AuditAttribute:属性
{
}
[AttributeUsage(AttributeTargets.Class)]
公共类AuditBoundaryAttribute:ContextAttribute
{
公共AuditBoundaryAttribute()
:base(“AuditBoundary”+Guid.NewGuid().ToString())
{
}
public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
{
添加(新的AuditProperty());
}
}
公共类AuditProperty:IContextProperty、IContributeObjectSink
{
公共字符串名
{
获取{return“AuditProperty”;}
}
公共bool IsNewContextOK(Context newCtx)
{
var p=newCtx.GetProperty(“AuditProperty”)作为AuditProperty;
if(p==null)
返回false;
返回true;
}
公共无效冻结(上下文newContext)
{
}
公共IMessageSink GetObjectSink(MarshallByRefObject对象,IMessageSink nextSink)
{
返回新的AuditSink(nextSink);
}
}
公共类审核接收器:IMessageSink
{
私人IMessageSink nextSink;
公共审计接收器(IMessageSink-nextSink)
{
this.nextSink=nextSink;
}
公共IMessage SyncProcessMessage(IMessage消息)
{
var消息=消息作为IMethodCallMessage;
IMethodReturnMessage returnMessage=null;
响应对象响应;
//这里会进行一些预处理
var newMessage=newmethodCallMessageWrapper(消息);
//调用要审核的方法
returnMessage=nextSink.SyncProcessMessage(newMessage)作为IMethodReturnMessage;
response=returnMessage.ReturnValue作为ResponseObject;
//在这里使用“响应”进行一些后处理
返回消息;
}
公共IMessageSink NextSink
{
获取{返回this.nextSink;}
}
公共IMessageCtrl-AsyncProcessMessage(IMessage消息,IMessageSink回复链接)
{
返回nextSink.AsyncProcessMessage(msg,replySink);
}
}

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

  • 执行预处理步骤
  • 调用异步方法
  • 使用
    ContinueWith()
    wait
    将后处理步骤作为继续添加到返回的
    任务中
  • 将继续
    任务
    返回给调用者
  • 如果您对线程池上执行的后处理没有意见,那么
    ContinueWith()
    可能更简单。如果需要在原始上下文上执行后处理,请使用
    wait

    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(), …);
    
    var responseTask=(任务)returnMessage.ReturnValue;
    Func后处理任务Func=async()=>
    {
    var响应=等待响应任务;
    //在这里使用“响应”进行一些后处理
    返回响应;
    }
    返回新的返回消息(postProcessTaskFunc(),…);