2

序文

DI フレームワークを使用すると、自分自身を撃つ可能性が現実にあるように感じます。
(私の選択したフレームワークは ninject なので、例ではそれを使用します。)

少し戻って、DIフレームワークが存在する理由を見てみましょう。
手動で DI を行う必要がないようにするには

そうです、Ninjects ドキュメントの精神で、 sDojoを作成する a があるとしましょうSamurai。これらSamuraiの は、作成時に が与えられIWeaponます。

class Samurai{
    readonly IWeapon weapon;

    public Samurai(IWeapon weapon){
        this.weapon = weapon;
    }
}

が を作成するときに をDojo使用することを理解しています。Kernel.Get<IWeapon>()Samurai

おっと
、Dojo をカーネルに結合しただけではありませんか?
また...カーネルを取得するにはどうすればよいですか: DI、シングルトン、サービスの場所?

DI フレームワークに依存しているため、DI の目的をすぐに打ち負かしたような気がします。忍者が倒されて忍者も死ぬとどうなりますか?

質問

DI フレームワークに結合せずに DI を使用するにはどうすればよいですか?

ポストフェイス

この質問は以前に尋ねられたと確信していますが、何も見つかりませんでした。コメントを使用して関連する質問を投稿し、知識をプールして最適な解決策を見つけられるようにしてください。

4

3 に答える 3

5

依存性注入を行うときの秘訣は、すべてのクラスにコンストラクターを介して依存性を注入させることです。このようにして、カーネルにルート オブジェクトから完全なオブジェクト グラフを作成させることができます。

kernel.Get<HomeController>()ただし、この「ルート オブジェクト」は、 (ルート オブジェクトの場合)を呼び出して直接解決する必要があるものHomeControllerです。したがって、アプリケーションのどこかで を呼び出す必要がありますkernel.Get。なしでは無理です。

秘訣は、これをアプリケーション内の理想的には 1 行のコードに最小化し、これをスタートアップ パスの近くに配置することです。おそらく、依存関係を登録した場所に近いでしょう。アプリケーションの残りの部分は、DI フレームワークの使用に気付かないままです。

使用するアプリケーション プラットフォームに応じて、コードを 1 行削除できる Ninject やその他のコンテナー用の統合パッケージもあります。たとえば、ASP.NET MVC には優れた拡張ポイントがあり、ControllerFactoryそのファクトリを呼び出すことができるプラグインを可能にkernel.Getします。

DI フレームワークに結合せずに DI を使用するにはどうすればよいですか?

常にいくつかの結合がありますが、理想的には、これはスタートアップ パスのみであるべきです。他のすべてのコードは、コンテナの使用に気付かないようにする必要があります。アセンブリの依存関係は引き続き存在しますが、この依存関係はスタートアップ プロジェクトにのみ存在し、ビジネス レイヤーには存在しません。

DI フレームワークが存在する理由を見てください: 手動で DI を行う必要がないようにするには

より正確には。DI は、アプリケーションをより保守しやすくするのに役立ちます。DI フレームワークは、アプリケーションのスタートアップ パス (別名コンポジション ルート) をより保守しやすくするのに役立ちます。

于 2012-12-18T12:21:26.770 に答える
2

実際には Service Locator の設計パターンは有害であると考えられていた (そして実際には多くの観点からアンチパターンと見なされていた) ため、コードからそれを使用することは強くお勧めしません。

Service Locator を使用すると、クラス ( class Dojo) とそのクライアントの間のインターフェースが不明確になります。クラス ヘッダーを読むことは、必要なコンテキストを理解することは不可能です: このクラスを適切に使用するにはどうすればよいですか? すべての要件を満たすには、何を内部に配置する必要がありますか?

実際、アプリケーションの 1 か所 (アプリケーションのルートなど)でのみコンテナー (サービス ロケーターとも呼ばれます) を使用している場合は、Composition Rootと呼ばれる別のパターンを使用することを好みます。MainHomeController

このトピックに関する本を見る​​ことを強くお勧めします。Mark Seeman による「Dependency Injection in .NET」では、このすべてのトピックをより詳細にカバーしています。

于 2012-12-18T12:51:00.527 に答える
1

DI コンテナーにある種の抽象化を行うこともできます。このようなインターフェースを考えてみましょう。

public interface IDependencyResolver
{
    T Get<T>();
}

次に、これを実装します-Ninjectの場合、次のようになります。

public class NinjectDependencyResolver : IDependencyResolver
{
    private readonly IKernel _kernel = new StandardKernel();

    public T Get<T>()
    {
        return _kernel.Get<T>();
    }
}

これは、Ninject をプロジェクト内の他のサードパーティ コンポーネントと同じように使用することを意味します。

IDependencyResolver resolver = new NinjectDependencyResolver();

必要に応じて、どこかで一度だけ見つける必要があります。次に、Ninject (または他のフレームワークの同様のコンテナー) によって提供されるIDependencyResolver代わりに、インスタンスを使用します。IKernel

DI コンテナーを切り替えるには、新しい を実装するだけIDependencyResolverです。

于 2012-12-18T12:25:10.017 に答える