1

ソリューションで Ninject を構成するための次のコード ブロックがあります。

public class NinjectDependencyScope : IDependencyScope
    {
        private IResolutionRoot resolver;

        internal NinjectDependencyScope(IResolutionRoot resolver)
        {
            Contract.Assert(resolver != null);

            this.resolver = resolver;
        }

        public object GetService(Type serviceType)
        {
            if (resolver == null)
            {
                throw new ObjectDisposedException("this", "This scope has already been disposed");
            }

            return resolver.TryGet(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            if (resolver == null)
            {
                throw new ObjectDisposedException("this", "This scope has already been disposed");
            }

            return resolver.GetAll(serviceType);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                IDisposable disposable = resolver as IDisposable;
                if (disposable != null)
                {
                    disposable.Dispose();
                }

                resolver = null;
            }
        }

私の意見では、ここで使用されている使い捨てパターンは必要ありません..

IDependencyScope は IDisposable ですが、IDisposable メンバーを構築している場合にのみクリーンアップする必要がありますが、コンストラクターに挿入されたリゾルバーはクラスによって所有 (作成) されておらず、IResolutionRoot は IDisposable から派生/実装していません...

私はここにいますか?

(参照用に IDisposable パターンに関するこの記事を確認してください)

(編集): これは実際には次のクラスで使用される基本クラスであるため、ここで IDisposable 実装を削除することはできません...

public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
    {
        private IKernel kernel;

        public NinjectDependencyResolver(IKernel kernel)
            : base(kernel)
        {
            this.kernel = kernel;
        }

        public IDependencyScope BeginScope()
        {
            return new NinjectDependencyScope(kernel.BeginBlock());
        }
    }
4

3 に答える 3

1

Ninject での私の経験では、IDisposable を実装するマネージド オブジェクトに関しては、最終的に破棄されるため、それほど心配する必要はありません。

ただし、管理されていないオブジェクトのラッパーである使い捨てオブジェクトがある場合 (たとえば、Office 相互運用アプリケーション オブジェクトをラップする C# クラスなど)、これらは最終的に Ninject によって破棄されるため、細心の注意を払う必要があります。確実にいつ​​言うことはありません。

コードの他の部分が既にクリーンアップされているこれらのリソースに依存している可能性があるため、これらのリソースをすばやくクリーンアップする必要がある場合があります (たとえば、これらのオブジェクトの 1 つを使用してワークブックを作成し、ワークブックの名前を変更する必要がある場合など)。その直後に、Application オブジェクトを解放する必要があります)。

この種のシナリオでは、私は DI の原則に違反し、オブジェクトを使用するときに新しいオブジェクトを作成し、自分で破棄する可能性があります。

このすべてを自分でテストして、Ninject での使用に適したオブジェクトとそうでないオブジェクトを把握し、それに応じて適切に使用してください。

于 2013-10-21T09:58:37.367 に答える
0

次の最小限の実装は正しいです (ただし、このクラスまたはそれから派生したクラスのいずれも管理されていないリソースを使用していない場合 - これはめったにありません)。

public void Dispose() {
    IDisposable disposable = resolver as IDisposable;
    if (disposable != null) {
        disposable.Dispose();
    }
    resolver = null;
}

詳細については、最小限の IDispose 実装を参照してください。

リゾルバーはそれなしで正しく破棄されるため、オプションです。つまり、リゾルバーによって管理されるリソースの解放を特に自分で制御する必要がある場合にのみ必要です (何?)。

于 2013-10-21T13:31:44.967 に答える
0

これが Autofac の場合であることはわかっています。Dispose が呼び出されるため、Autofac から解決したクラスの破棄について心配する必要はありません。Ninjectも同様であると確信しています。

于 2013-10-21T09:18:43.220 に答える