2015-11-21 8 views
6

System.Runtime.Remoting.Messaging.CallContextAsyncLocalの両方のクラスは完全なCLRを使用してのみ使用できます。これにより、ポータブルクラスライブラリやWindows Phoneアプリケーションを使用しているときに、特にWindows Phone APIが非同期のみになっているため、非同期スコープを実行することが非常に難しくなります。したがって、非同期/待機を使用しないという選択肢はありません。PCLとWindows Phoneアプリケーションでの非同期スコープの実装

これは実質的に意味することはWPFまたはリサイズして、我々はこのようなメソッドを書くことができるということです:WPFとWinFormsので

private async void button_Click(object sender, EventArgs e) 
{ 
    CallContext.LogicalSetData("x", new object()); 
    await Something(); 
    var context = CallContext.LogicalGetData("x"); 
} 

は、フレームワークは、それぞれが独自のコンテキストを取得して同じボタンをクリックすることを保証し

孤立して実行することができます。 ThreadLocal<T>[ThreadStatic]を使用すると、すべてのクリックがUIスレッドで実行されるため、同じ結果を達成することは難しいです。

私の質問はどのように我々はCallContextAsyncLocal<T>をサポートしていないWindowsの携帯電話、ストアおよびその他のアプリケーションの種類でこの問題を解決するだろう、とは?

いくつかの背景情報:

は、非常に多くの場合、我々はコンテキストのいくつかの並べ替えで実行する(ビジネス)ロジックをしたいです。このコンテキストには、ビジネスロジックが操作を通じて使用できる情報を含めることができます。サーバー環境では、データベーストランザクションで要求を実行する必要があるため、現在のユーザー、テナントIDなどにアクセスする必要があるため、想像するのは簡単です。ただし、クライアントアプリケーションであっても、現在実行中の操作の相関IDまたはログのコンテキスト。そのような操作(クリックイベントのようなもの)では、追加のサービス(Composition Rootから)を解決する必要があります。操作がうまくいくためには、クライアント操作全体を通して同じコンポーネントを再利用する必要があるかもしれません。これは、Composition Rootが実行中のコンテキストを認識する必要があることを意味します。

サービスのパブリックAPIのメソッド呼び出しを使用して、すべての情報をシステム全体に渡すことができますが、アプリケーションのAPIを実装の詳細で汚染させるだけでなく、システム全体を通じてこれらの情報をすべて渡す必要があるため、コンポーネントの1つに対する単純な内部変更が、すべてのメソッド呼び出しを通じてコールスタックの上に伝播するため、保守に関する深刻な問題が発生します。 Composition Rootについては、DIライブラリの一部のキャッシュ/スコープオブジェクトをアプリケーションで渡したくないのは間違いありません。これは、ビジネスロジックを外部ライブラリに密接に結びつけるためです。明らかに、どちらもservice locatorのようなものを渡すつもりはありません。

CallContextまたはAsyncLocal<T>などのスコープを実装することは、クライアントアプリケーションでは非常に重要です。

答えて

3

今日は簡単な解決策はありません。申し訳ありません。 Windows Phone(最終的に)が「電話のWindows 10」(つまり、AsyncLocal<T>)になると、これが可能になります。しかし今のところ...

これを行う最も簡単な方法は、明示的に(パラメータとして)または暗黙的に(メンバー変数としてthis)コンテキストを渡すことです。

カスタムオーバスターでこれを限定版にすることもできます。しかし、恐ろしく複雑なことに加えて、その解決策では、アプリケーション全体でawaitをすべて変更する必要があります(または、同じ効果を達成するためにコンパイル後のIL再書き込みを使用します)。

+2

クラップス。私が望んでいた答えではありません。 – Steven

+0

@スティーブン:申し訳ありません!慰安賞として、暗黙のコンテキストが素晴らしい設計ではないと信じることは大歓迎です。それらはコンテキストを記録するのに適しています(複数のログメッセージを1つの論理的な "活動"にグループ化する)。見えないコンテキストは、真のビジネスデータ/ロジックのための貧弱なメカニズムです。システムをテストして維持するのが難しくなります。私は数多くの非同期コードを書いています(「アクティビティ」相関を除く)、デバッグ時に暗黙のコンテキストを使用して因果関係スタックを作成します。 –

+0

私はそれがビジネスロジックにとっては悪いことに同意しますが、(TransactionScopeのような)透過的なコンテキストは、インフラストラクチャ上の懸念に最適であり、実際には開発者の生活をはるかに容易にします。 [Simple Injector](https://simpleinjector.org)(DI lib)は、このコンセプトを取り入れたスコープのあるライフスタイルの設計に基づいており、ビジネスロジックを完全に無視することができるため、開発者の生活がはるかに容易になりますシステム全体を通してDIコンテナのスコープを通過すると、DIコンテナが強く結合しますが、これは悪い習慣です。 – Steven

関連する問題