私のサービスクラスでRAIIパターンに従おうとしています。つまり、オブジェクトの構築時に完全に初期化されます。しかし、私は非同期APIの問題に直面しています。問題のクラスの構造は、私もそれがスレッドセーフにするために、ImportantValue
ゲッターに副作用を取り除くためにターゲットにしています非同期待機パターンを使用してオブジェクトを初期化する方法
class ServiceProvider : IServiceProvider // Is only used through this interface
{
public int ImportantValue { get; set; }
public event EventHandler ImportantValueUpdated;
public ServiceProvider(IDependency1 dep1, IDependency2 dep2)
{
// IDependency1 provide an input value to calculate ImportantValue
// IDependency2 provide an async algorithm to calculate ImportantValue
}
}
を次のようになります。
ServiceProvider
のユーザーは、そのインスタンスを作成し、ImportantValue
というイベントにサブスクライブし、最初にImportantValue
を取得します。そしてここで、初期値とともに問題が起こります。 ImportantValue
は非同期に計算されるため、クラスはコンストラクターで完全に初期化できません。この値を最初はnullにしても構いませんが、最初に計算される場所が必要です。そのための自然な場所はImportantValue
のゲッターかもしれませんが、私はそれをスレッドセーフで、副作用なしにすることを目標にしています。
私は基本的にこれらの矛盾に固執しています。私を助けて、代替案を提供してもらえますか? niceは実際には必要ではないが、副作用やプロパティのスレッドセーフなどは不要ですが、コンストラクタで値を初期化することは必須です。
ありがとうございます。
編集:もう1つ追加します。インスタンス化のためにNinjectを使用していますが、わかっている限り、バインディングを作成するための非同期メソッドはサポートされていません。コンストラクタでタスクベースの操作を開始するアプローチはうまくいくが、私はその結果を待つことはできない。
I.e. 2次のアプローチはコンパイルされません、タスクが返されているので、ない私のオブジェクト(の答えとして、これまで提供):
Kernel.Bind<IServiceProvider>().ToMethod(async ctx => await ServiceProvider.CreateAsync())
または
がKernel.Bind<IServiceProvider>().ToMethod(async ctx =>
{
var sp = new ServiceProvider();
await sp.InitializeAsync();
})
単純な結合動作しますが、私は待っていませんよStephen Clearyの提案するように、コンストラクターで非同期初期化を開始した結果:
Kernel.Bind<IServiceProvider>().To<ServiceProvider>();
...それは私にはうまく見えません。
私はRAIIだとは思わない。おそらく最も重要な部分はリソースの割り当て解除です(ただし名前はそれを示唆していません)。 GCは非決定的な割り当て解除を引き起こすため、これはC#にはあまり関係ありません。 – svick
私のlibary [AsyncContainer](https:// github。com/RafaelSalguero/AsyncContainer) – rafael