In asp.net - using Message Handlers - 我可以通过添加消息处理程序来自定义请求/响应。
因此,请求进入,通过多个消息处理程序,然后响应通过相同的处理程序(反方向)返回。
所以,例如:如果我附加了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());
结果是:
如你所见,就像我说的那样like this article says:执行是对称的。
大
但后来我心里想 - 他们是如何做对称执行的?
所以我成功使用continuation创建了自己的对称执行演示:
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
之前),然后运行第二个部分(在{之后) {1}})来自每种方法。
类似的东西:
所以我看看reference source for base.Sendasync
:但无法找到ContinueWith
如何进行这种对称执行
问题
base.Sendasync
如何在没有一种方法调用另一种方法的情况下进行对称执行?
答案 0 :(得分: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();
}
}
答案 1 :(得分: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();
}
}