2

在 asp.net 中 - 使用消息处理程序- 我可以通过添加消息处理程序来自定义请求/响应。

因此,一个请求进入,经过多个消息处理程序,然后响应通过相同的处理程序返回(方向相反)。

在此处输入图像描述

因此,例如:如果我附加 2 个消息处理程序:( 是的,我知道,async/await 是首选,但那是来自一本书)

public class CustomMessageHandler1 : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Debug.WriteLine("CustomMessageHandler1 request invoked");
        return base.SendAsync(request, cancellationToken)
                   .ContinueWith(task =>
                                      {
                                      Debug.WriteLine("CustomMessageHandler1 response invoked");
                                      var response = task.Result;
                                      return response;
                                      });
    }
}


public class CustomMessageHandler2 : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Debug.WriteLine("CustomMessageHandler2 request invoked");
        return base.SendAsync(request, cancellationToken)
                   .ContinueWith(task => 
                                      {
                                      Debug.WriteLine("CustomMessageHandler2 response invoked");
                                      var response = task.Result;
                                      return response;
                                 });
    }
}

我们不要忘记在 global.asax 中注册它们:

var config = GlobalConfiguration.Configuration;
config.MessageHandlers.Add(new CustomMessageHandler1());
config.MessageHandlers.Add(new CustomMessageHandler2());

结果是:

在此处输入图像描述

正如你所看到的,就像我说的和这篇文章说的:执行是对称的。

伟大的。

但后来我心想——他们是如何做到对称处决的?

所以我成功地使用延续创建了我自己的对称执行演示:

void Main()
{
 Method1() ;    
}

  public async  Task  Method1 ()
  {
   Console.WriteLine ("Method_1"); //alias to request
   await Method2();
   Console.WriteLine ("Finished Method_1");  //alias to response
  }


 public async Task  Method2 ()
 {
  Console.WriteLine ("Method_2");  //alias to request
  await Task.FromResult("...");//dummy
  Console.WriteLine ("Finished Method_2");  //alias to response

 }

结果确实是对称的:

Method_1
Method_2
Finished Method_2
Finished Method_1

但是在我的代码中Method1 Method2就是它起作用的原因!.

但是在上面的第一个代码中 - 他们不互相调用!就像某些东西只从每个方法调用第一部分(在 之前ContinueWith),然后从每个方法运行第二部分(在 之后ContinueWith)。

就像是 :

在此处输入图像描述

因此,我查看了以下参考源base.Sendasync :但找不到如何base.Sendasync进行这种对称执行

问题

如何在 base.Sendasync没有一种方法调用另一种方法的情况下进行对称执行?

4

2 回答 2

4

这是适用于您的控制台应用的 Web API 管道。

abstract class BaseHandler // HttpHandler
{
    public abstract Task MyMethodAsync();
}

abstract class Handler : BaseHandler // MessageHandler
{
    public Handler InnerHandler { get; set; }

    public override Task MyMethodAsync()
    {
        if (this.InnerHandler != null)
            return this.InnerHandler.MyMethodAsync();
        else
            return Task.FromResult<object>(null);
    }
}

class Handler1 : Handler
{
    public override async Task MyMethodAsync()
    {
        Console.WriteLine("Method_1"); //alias to request
        await base.MyMethodAsync();
        Console.WriteLine("Finished Method_1");  //alias to response
    }
}

class Handler2 : Handler
{
    public override async Task MyMethodAsync()
    {
        Console.WriteLine("Method_2"); //alias to request
        await base.MyMethodAsync();
        Console.WriteLine("Finished Method_2");  //alias to response
    }
}

class LastHandler : Handler
{
    public override async Task MyMethodAsync()
    {
        // Does nothing
        await base.MyMethodAsync();
    }
}

class Program
{
    static void Main(string[] args)
    {
        List<Handler> handlers = new List<Handler>();
        // You do this when you add the handler to config
        handlers.Add(new Handler1());
        handlers.Add(new Handler2());

        // This part is done by HttpClientFactory
        Handler pipeline = new LastHandler();

        handlers.Reverse();
        foreach (var handler in handlers)
        {
            handler.InnerHandler = pipeline;
            pipeline = handler;
        }

        pipeline.MyMethodAsync().Wait();
    }
}
于 2014-10-18T13:44:50.720 回答
3

每个委托处理程序都知道它的“下一个”处理程序,并且DelegatingHandler.SendAsync 确实调用SendAsync了下一个(“内部”)处理程序。你可以把它想象成一个链表,如下所示:

public abstract class MyDelegatingHandler
{
  private readonly MyDelegatingHandler _next;

  public MyDelegatingHandler(MyDelegatingHandler next = null)
  {
    _next = next;
  }

  public virtual Task SendAsync()
  {
    if (_next == null)
      return Task.FromResult(0);
    return _next.SendAsync();
  }
}
于 2014-10-18T13:27:40.927 回答