0

MVC アプリケーションで Ninject を使用しており、Unit of Work リポジトリ パターンを実装しようとしています。

具体的には、一般的な IUnitOfWork インターフェイスを定義しました。次に、このインターフェイスのインスタンスを他の (ビジネス ロジック クラス) のコンストラクターで使用したいと考えています。これが私のコントローラーの始まりです...

public class CompanyController : Controller
{
    private readonly IUnitOfWork UnitOfWork;
    private readonly ICompanyService CompanyDb;
    private readonly IEmployeeService EmployeeDb;

    public CompanyController(IUnitOfWork unitOfWork)
        : base()
    {
        this.UnitOfWork = unitOfWork;
        // This following construction is the problem...
        this.CompanyDb = new ICompanyService(this.UnitOfWork);
        this.EmpoloyeeDb = new IEmployeeService(this.UnitOfWork);
    }

    // Rest of Controller implementation
}

コントローラー コンストラクターは正しく動作しますが、さまざまなビジネス ロジック クラスを構築するクリーンな方法を見つけて、UnitOfWork オブジェクト内のリポジトリを参照できるようにしたいと考えています。

問題は、インターフェイスから新しいビジネス ロジック オブジェクトをインスタンス化できないことです。つまり、次のコードが失敗します。

this.CompanyDb = new ICompanyService(this.UnitOfWork);

ICompanyService インターフェイスを具体的な実装に「配線」するものは何もないためです。私がやりたいことは、DI (Ninject) を使用して、物理クラスのコンストラクターが次のようになる ICompanyService のインスタンスを作成することです。

public class CompanyService : ICompanyService {

    private readonly UnitOfWork db;

    public CompanyService(IUnitOfWork unitOfWork) {
        this.db = unitOfWork as UnitOfWork;
    }
}

最終的な解決策 Joshscorp と Dbaseman からの提案 (ありがとう) に加えて、次のようにコードを構成しました。

public class CompanyService : ICompanyService {

    private readonly UnitOfWork db;

    public CompanyService(IUnitOfWork unitOfWork) {
        this.db = unitOfWork as UnitOfWork;
    }

    // Rest of implementation
}


public class CodeFirstController : Controller {

    private readonly IUnitOfWork UnitOfWork;
    private readonly ICompanyService CompanyDb;
    private readonly IEmployeeService EmployeeDb;


    public CodeFirstController(
        IUnitOfWork unitOfWork,
        ICompanyService companyDb,
        IEmployeeService employeeDb
    ) : base() {
        this.UnitOfWork = unitOfWork;
        this.CompanyDb = companyDb;
        this.EmployeeDb = employeeDb;
    }

    // Rest of implementation
}

Ninject モジュールは次のとおりです。

public class CodeFirstModule : NinjectModule {
    public override void Load() {
        string connectionString = ConfigurationManager
            .ConnectionStrings["CompanyConnection"]
            .ConnectionString;


        Bind<CodeFirst.DAL.IUnitOfWork>()
           .To<CodeFirst.DAL.EntityFramework.UnitOfWork>()
           .InRequestScope()
           .WithConstructorArgument("connectionString", connectionString);

        Bind<CodeFirst.DAL.ICompanyService>()
           .To<CodeFirst.DAL.EntityFramework.CompanyService>()
           .InRequestScope();

        Bind<CodeFirst.DAL.IEmployeeService>()
           .To<CodeFirst.DAL.EntityFramework.EmployeeService>()
           .InRequestScope();
   }
}

IUnitOfWork バインディングの 'InRequestScope()' メソッドは、UnitOfWork クラスの同じインスタンスが依存クラス CompanyService および EmployeeService のコンストラクターで使用されることを保証します。

これはまさに私が探していたもの、つまり依存サービス クラスによって参照される IUnitOfWork オブジェクトの単一インスタンスを実現します。

4

1 に答える 1

2

まず第一に、インターフェースを新しくすることはできず、具体的なクラスだけを新しくすることができます。

new ICompanyService動作しません。

次に、通常MVCの場合は、DependencyResolverを使用してオブジェクトを解決していると思います。これは、一部の人によるとアンチパターンです。依存関係を解決するために何を使用するかに関係なく、アプリケーションへの単一のエントリポイント、つまりGlobal.asaxなどのリクエストごと、および依存関係オブジェクトグラフをロードするための何らかのブートストラッパーが常に必要です。

あなたの例では、私が変更するのはコンストラクターであり、それを取り入れICompanyServiceIEmployeeService

public class CompanyController : Controller
{
    private readonly IUnitOfWork unitOfWork;
    private readonly ICompanyService companyDb;
    private readonly IEmployeeService rmployeeDb;

    public CompanyController(IUnitOfWork unitOfWork,
        ICompanyService companyDb, 
        IEmployeeService  employeeDb)
    {
        this.unitOfWork = unitOfWork;
        this.companyDb = companyDb;
        this.empoloyeeDb = employeeDb;
   }

    // Rest of Controller implementation
}

これは、アプリのエントリポイントにNinjectまたは任意のIoCコンテナの具体的な実装を登録した場合に発生しますICompanyServiceIEmployeeServiceNinjectに精通していないため、お勧めしません)

それでは、インスタンスはどのようにして具体的なオブジェクトのコンストラクターIUnitOfWorkに注入されたのでしょうか。ICompanyServiceのコンストラクターに注入されたのと同じ方法CompanyControllerです!

于 2012-09-03T16:13:55.880 に答える