ASP.NETコア2から始めています。メッセージハンドラにメッセージを書き込む要求に関係する各要素の方法が必要です。AsyncLocalを使用してリクエスト情報を保存しますか?
いくつかの制限事項:
- 我々は
HttpContext.Items
(HttpContext
は、我々はコントローラの内部で使用しているクラスでは使用できません、と私たちはそこに全体のコンテキストを転送するために好きではない)を使用しません。 - 私たちは複数の異なるサービスを持っているので、コンストラクタにあまりにも多くのパラメータを持つので、依存性のない注入を使用しようとしました。
- また、
async
/await
と併用する必要があります。
AsyncLocal<T>
を使用してアプローチを試みました。私たちは、クラスを作成したことについては
:
public class NotificationExecutionContext
{
private static readonly AsyncLocal<NotificationHandler> NotificationHandler =
new AsyncLocal<NotificationHandler>();
public static NotificationHandler Instance =>
NotificationHandler.Value ?? (NotificationHandler.Value = new NotificationHandler());
}
ごとの要求生きるべき作成NotificationHandler
、があります。 NotificationHandler
はあなたに/コレクションから取得/メッセージを追加することができます単純なクラスです。このソリューションにより
public class NotificationHandler : INotificationHandler
{
public List<NotificationBase> Notifications { get; } = new List<NotificationBase>();
public void AddNotification(NotificationBase notification)
{
Notifications.Add(notification);
}
public void AddNotificationRange(List<NotificationBase> notifications)
{
Notifications.AddRange(notifications);
}
}
、私は簡単にこのコンテキストのNotificationHandler
を取得し、通知を追加することができます。ミドルウェアインサイド
NotificationExecutionContext.Instance.AddNotification(new NotificationBase(){..})
、我々はResponse.OnStarting()
イベントを待っているし、我々はNotificationHandler
からすべてのメッセージを取得し、それらに応答ヘッダを追加します。
public async Task Invoke(HttpContext context)
{
var e = NotificationExecutionContext.Instance; // Required so that notification handler will be created in this context
context.Response.OnStarting((state) =>
{
List<NotificationBase> notifications = NotificationExecutionContext.Instance.Notifications;
if (notifications.Count > 0)
{
string messageString = JsonConvert.SerializeObject(notifications, Formatting.None);
context.Response.Headers.Add("NotificationHeader", messageString);
}
return Task.FromResult(0);
}, null);
await Next(context);
}
このコードは動作しますが、それが落とし穴です我々は知りません?または、より良い解決策がありますか?