2

私は自分自身の学習/成長のために IoC コンテナーを作成しています。通常、私は次のようなものを書きます。

using(DisposableObject dispObj = new DisposableObject())
{
    UserRepository users = new UserRepository(dispObj);

    // Do stuff with user.
}

次のようになります。

using(IDisposableObject dispObj = Container.Resolve<IDisposableObject>())
{
    IUserRepository users = Container.Resolve<IUserRepository>();

    // Do stuff with user.
}

DisposableObject を抽象化しusingて、IoC を使用するときにスコープで使用される唯一のインスタンスになるようにするにはどうすればよいですか? Autofac がどのようにそれを行うのかを理解しようとしていますが、完全にはわかりません。

編集:オブジェクトがusingスコープでインスタンス化される場合、その型 (この場合はIDisposableObject) を解決するためのすべての呼び出しは、新しいインスタンスではなく、スコープ変数を返す必要があります。usingステートメントの後、別のステートメントが呼び出されると、新しいインスタンスResolve<IDisposableObject>が返されることも重要です。

4

2 に答える 2

2

この方法で使い捨てオブジェクトを使用するときに覚えておくべきことは、コンテナー内の参照も破棄されるため、理想的には Resolve<> を介してインスタンスを返すときは、毎回新しいインスタンスを返す必要があるということです。

あなたがする必要があるのは、型をコンテナに登録するときに、Shared (Singleton) または NonShared のいずれかの動作を指定できるようにすることです。

Container.RegisterType<IDisposableObject>(CreationPolicy.NonShared);

using (var disposable = Container.Resolve<IDisposableObject>()) {

}

毎回新しいインスタンスが作成されるため、上記は NonShared インスタンスに対して機能するため、安全に破棄できます。CreationPolicy = Shared で上記を試した場合、Singleton は破棄されるため、今後のアクセスで ObjectDisposedException が発生する可能性があります。

この動作を組み込むことで、CreationPolicy = Shared を渡すことで Singleton インスタンスを作成できます。例:

Container.RegisterType<IUserRepository>(CreationPolicy.Shared);

using (var disposable = Container.Resolve<IDisposableObject>()) {
    var userRepository = Container.Resolve<IUserRepository>();
    // only one instance of user repository is created and persisted by the container.
}

それが役立つことを願っていますか?

以前に MEF を使用したことがある場合、この用語はおなじみかもしれません。

編集:したがって、私の理解では、次のようなことをしたいということです:

using (var repository = Container.Resolve<IUserRepository>())
{
  var other = Container.Resolve<IUserRepository>();
  // should resolve to the same instance.
}

コンテナー内の使い捨てオブジェクトを監視する何らかの方法を見つける必要があります。おそらく、追加の作成ポリシー、SharedScope を導入します。たとえば、次のようになります。

Container.Register<IUserRepository, UserRepository>(CreationPolicy.SharedScope);

ここで、コンテナーを使用して型を解決するときに、アイテムの CreationPolicy を把握する必要があります。アイテムが SharedScope であり、作成されていない場合は、そのインスタンスを作成して返します。

インスタンスを解決し、それが既に作成されている場合は、既存のインスタンスを返します。

そのアイテムで Dispose が呼び出された場合、インスタンスを削除するためにコンテナーにコールバックする何らかの方法が必要です。

編集2

うーん、そう簡単に判断する方法はありません。私が考えることができる唯一の方法は、別のインターフェースを導入することです:

public interface IMonitoredDisposable : IDisposable
{
  bool IsDisposed { get; set; }
}

オブジェクトが破棄されるときは、IsDisposed プロパティが設定されていることを確認してください。コンテナからそのプロパティを監視できますか?

于 2010-06-30T18:07:12.990 に答える
2

Owned<Foo>の代わりに型のオブジェクトを返すことができますFoo

Owned<T>次のようになります。

public class Owned<T> : IDisposable
{
   private readonly Container container;
   private readonly T value;

   public Owned(Container container, T value)
   {
      this.container = container;
      this.value = value;
   }

   public T Value { get { return value; } }

   public void Dispose()
   {
      this.container.ReleaseOwned(this);
   }

}

これで、クライアントのプルは、それ自体が破棄可能でないOwned<Foo>場合でも、オブジェクトを破棄することによって、オブジェクトの処理が完了したことをコンテナーに通知できます。Fooこのようにして、コンテナーはオブジェクトとその依存関係をいつクリーンアップするかを認識し (これも破棄可能ですが、クライアントからは見えない可能性があります)、目的の動作を実装できます。

Autofac は非常によく似た処理を行います。Nicholas Blumhardt によるブログ投稿、The Relationship Zooを参照してください。彼はこの概念を紹介しています。

于 2010-07-01T01:01:50.957 に答える