0

https://github.com/int6/CoiniumServ/blob/develop/src/CoiniumServ/Pools/Pool.cs

これは私のプールクラスです。クラスを破棄するときにそれが必要です。すべての依存関係は機能を停止し、それ自体を破棄する必要があります。

私は処分するためにすべての依存関係に idisposable を実装しようとしましたが、うまくいきません。

また、スレッドで関数を実行するスレッドを実装し、スレッドの中止でそれを破棄します。それも機能しません。

これを行う他の方法はありますか?

4

1 に答える 1

1

コンポーネントは、注入された依存関係を破棄してはなりません。その主な理由は次のとおりです。

  1. そのコンポーネントはそれらを作成しなかったため、それらの依存関係を破棄する必要があるかどうかわかりません。
  2. 消費者は、依存関係が破棄可能であることを意識するべきではありません。

コンポーネントがより長いライフタイムを持つサービスに依存することは非常に一般的です。消費するコンポーネントがその依存関係を破棄する場合、使用するように構成されている間は依存関係を使用できなくなるため、アプリケーションは壊れます。簡単な例を次に示します。

// Singleton
private static readonly IRepository<User> repository = new UserRepository();

public IController CreateController(Type controllerType) {
    if (controllerType == typeof(UserController)) {
        return new UserController(repository);
    }

    // ...
}

この例には、 singletonUserRepositoryと transientが含まれていUserControllerます。要求ごとに、新しいUserControllerものが作成されます (ASP.NET MVC アプリケーションを想像してみてください。これは理にかなっています)。がUserControllerを破棄するUserRepositoryと、次のリクエストはUserController、既に破棄された に依存する を取得しUserRepositoryます。これは明らかに悪いでしょう。

しかし、これ以外に実装IRepository<T>すべきではありませんIDisposable。実装IDisposableとは、抽象化が実装の詳細を漏らしていることを意味し、そのため、次のように述べられているDependency Inversion Principleに違反しています。

抽象化は詳細に依存すべきではありません。詳細は抽象化に依存する必要があります。

抽象化での実装は、その抽象化のすべての実装がそれ自体を破棄する必要があることIDisposableを完全に 100% 確信している場合にのみ意味があります。しかし、これはめったにありません。単体テストに実装があることを想像してみてください。このような偽の実装は破棄を必要としないため、すべての実装が破棄を必要とするわけではなく、実装の詳細を漏らしています。FakeRepository<T>

これは単に、IDisposableインターフェイスを実装に移動する必要があることを意味します。例えば:

public interface IRepository<T> { }

public class UserRepository : IRepository<User>, IDisposable { }

IDisposableすべてのコンシューマーが呼び出すとは限らないが、抽象化されたインターフェイスを持つことは、次のように述べているインターフェイス分離の原則Disposeに違反していることにも注意してください。

クライアントは、使用しないメソッドに依存することを強制されるべきではありません。

これの利点は、コンシューム コンポーネント ( などUserController) が誤って呼び出さDispose()れ、システムが破損する可能性がなくなることです。

もう 1 つの利点は、コンポーネントが依存関係を破棄する必要がないため、ほとんどのコンポーネントで破棄ロジックが残らず、システムが大幅に単純になり、保守しやすくなることです。

于 2015-07-04T12:39:16.227 に答える