5

一般に、メソッドを使用してクラスをインスタンス化し、フィールドやプロパティを使用しない場合、多くのオーバーヘッドが発生しますか?

コンストラクター インジェクションを多用する ASP.NET MVC アプリケーションを開発しており、一部のコントローラーにはこれまでに最大 10 個の依存関係があります。しかし、依存関係の数が多いためIMyAppServiceProvider、MVC 3 の DependencyResolver を介して、すべての依存関係への汎用アクセスを提供するインターフェイスとクラスに頼りました。

アプリケーション固有のコードをすべて取り除き、基本的なセットアップでGistを作成しました (これには、以下で説明する BaseController のセットアップは含まれません)。

を受け入れる BaseController クラスも作成しましたIMyAppServiceProvider。すべてのコントローラーは、この基本クラスから継承します。基本クラスはIMyAppServiceProviderオブジェクトを受け取り、さまざまなサービスすべての変数を保護しています。コードは次のようになります。

public class BaseController
{
    protected IService1 _service1;
    protected IService2 _service2;
    protected IService3 _service3;
    // ...

    public BaseController(IMyAppServiceProvider serviceProvider)
    {
        _service1 = serviceProvider.GetService<IService1>;
        _service2 = serviceProvider.GetService<IService2>;
        _service3 = serviceProvider.GetService<IService3>;
        // ...
    }
}

これにより、コントローラーのコードが「きしむようにきれい」になります。プライベート/保護された変数、コンストラクターでの割り当てはなく、サービスは基本クラスの保護された変数によって参照されます。 ただし、特定のコントローラーがそれらすべてを使用するかどうかに関係なく、すべての要求は、アプリケーションが使用するすべてのサービスをインスタンス化します。

私のサービスは単純で、いくつかのビジネス ロジックとデータベースのやり取りを伴うメソッド呼び出しだけが含まれています。これらはステートレスであり、クラス フィールドやプロパティはありません。したがって、インスタンス化は高速である必要がありますが、これがベスト プラクティスであるかどうか疑問に思っています (これは用語の定義です)。

4

2 に答える 2

7

特定のコントローラーがそれらすべてを使用するかどうかに関係なく、すべてのリクエストは、アプリケーションが使用するすべてのサービスをインスタンス化します。

あなたは自分で質問に答えたと思いますが、これは良いアプローチではありません。さらに、このような種類の依存関係解決 (Service Locator 注入) を使用することは、コントローラーの API が乱雑になるため、悪い習慣です。コントローラー クライアントは、特定のコントローラーに本当に必要なサービスを認識していないため、予期しない実行時エラーが発生する可能性があり、単体テストも混乱します。

ところで、もう 1 つの提案 - 基本クラスと見なされるすべてのクラスをabstractキーワードでマークします。このようにして、具体的なクラスとして使用することを避けることができます。基本クラスの設計と実装は具体的な設計上の決定であるため、設計の意図を明確にしてください。

インスタンス化のコストに関しては、あなたの場合は大きな違いはありませんが、一般的に、重いオブジェクトのインスタンス化のコストを削減するには、次のことができます。

  • プロトタイプ パターンを使用して、「特定のアプリケーションにとって法外にコストがかかる場合に、標準的な方法 (たとえば、'new' キーワードを使用) で新しいオブジェクトを作成する固有のコストを回避する」 (c)ウィキペディア
  • 所有者オブジェクトのライフタイムの開始時から不要なサービスには遅延初期化を使用して、オンデマンドで初期化されるようにします。.NET Framework 4.0 以降では、組み込みのLazy(T) クラスを使用できます
于 2012-03-13T20:25:19.987 に答える
2

ここで探している解決策は、カスタム コントローラー ファクトリを使用することだと思います。そうすれば、作成された各コントローラーには、必要な依存関係が正確に含まれます。これは、 weblogs.asp.netからの StructureMap の 1 つです。

using StructureMap; 
public class StructureMapControllerFactory : DefaultControllerFactory { 

    protected override IController GetControllerInstance(Type controllerType) {
        try {
           return ObjectFactory.GetInstance(controllerType) as Controller;
        }
        catch (StructureMapException) {
            System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());
            throw;
        }
    }
}

protected void Application_Start() {
    RegisterRoutes(RouteTable.Routes);

    //Configure StructureMapConfiguration
    // TODO: config structuremap        

    //Set current Controller factory as StructureMapControllerFactory
    ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); 
}
于 2012-03-13T20:28:25.640 に答える