3

次のセクションでn層アプリケーションを作成しています。

  • MyApp.DAL-データアクセス層(EF 5、SQLバックエンド)
  • MyApp.BLL-ビジネスレイヤー
  • MyApp.WcfService-サービスレイヤー
  • MyApp.WpfClient-フロントエンド
  • MyApp.Modelsは、すべてのPOCOを保持する共有プロジェクトです。

各レイヤーの「Country」エンティティの例を示します。最初はモデルです。StatefulObjectは、切断されたクライアントからのエンティティの状態を追跡するのに役立つことに注意してください(JuliaLernerのプログラミングEF第2版第18章による)。

public class Country : StatefulObject
{
    [Key]
    [StringLength(2)]
    public string Code { get; set; }
    [Required]
    [StringLength(50)]
    public string Name { get; set; }
}

DALには、ICountryRepository(基本的なCRUD)とCountryRepositoryがあります。これがコンストラクターです。

public class CountryRepository : ICountryRepository, IDisposable
{
    MyDbContext _db;

    public CountryRepository()
    {
        _db = new MyDbContext();
    }

    //Implement ICountryRepository (basically CRUD), etc...
}

私のBLLには、次のようなICountryLogic、CountryLogic、IBusinessLayer、およびBusinessLayerがあります。

public class CountryLogic : ICountryLogic
{
    ICountryRepository _countryRepository;

    public CountryLogic(ICountryRepository countryRepository)
    {
        _countryRepository = countryRepository;
    }

    //implement ICountryLogic members, etc...
}

public class BusinessLayer : IBusinessLayer
{
    public ICountryLogic CountryLogic { get; set; }

    public BusinessLayer()
    {
        CountryLogic = new CountryLogic(new CountryRepository());
    }
}

次に、新しいビジネスレイヤーをインスタンス化し、次のような操作を実行するサービスメソッドの例を示します。

public class CountryService : ICountryService
{
    public IEnumerable<Country> GetAll()
    {
        IBusinessLayer bl = new BusinessLayer();
        return bl.CountryLogic.GetAll();
    }

    //implement other service operations
}

次に、WPFクライアントは次のようにサービスを使用できます。

CountryServiceClient countryService = new CountryServiceClient();

var countries = countryService.GetAll();

さて、BLLとWPFフロントエンドの間にWCFサービスを配置する前に、私のWPFフロントエンドは依存性注入を使用することができ、この醜さはありませんでした。

public class BusinessLayer : IBusinessLayer
{
    public ICountryLogic CountryLogic { get; set; }

    public BusinessLayer()
    {
        CountryLogic = new CountryLogic(new CountryRepository());  // <<<< UGLY HERE
    }
}

代わりに、次のようにDIとコンストラクターインジェクションを使用します。

public class BusinessLayer : IBusinessLayer
{
    public ICountryLogic CountryLogic { get; set; }

    public BusinessLayer(ICountryLogic countryLogic)
    {
        CountryLogic = countryLogic;
    }
}

次に、インターフェイスと実装をWPFのコンテナーに登録するだけです。私の質問は、それらをクラスライブラリ(BLL内)に登録するにはどうすればよいですか?クラスライブラリにはコンポジションルートまたはエントリポイントがないため、その方法がわかりません。SimpleInjectorを使用しています。

または、WcfサービスでDIを使用することもできますが、ICountryRepositoryをCountryRepositoryに登録できるように、サービスにDALへの参照が必要になります。これは正しくないようです。サービスレイヤーはBLLのみを参照する必要があるため、BLLにDIを設定する必要があります。ありがとう。

4

2 に答える 2

4

私が見ているように、あなたはここでいくつかの抽象化を見逃しています。WPFクライアントは、WCFサービスを間に配置するという事実を気にする必要はありません。たとえば、かなり醜いXXXServiceクラス(などCountryService)を使用する代わりに、コマンドメッセージとクエリメッセージをネットワーク経由で送信することを検討してください。このようにして、WPFクライアントが依存できる単純なインターフェイスを定義ICommandHandler<TCommand>できます。IQueryHandler<TQuery, TResult>その場合、ネットワークを介して通信するかどうかを知る必要はありません。これらの抽象化により、サーキットブレーカーのデザインパターンなどの横断的関心事(デコレータとして)を追加することもできます。、これは、接続の信頼性が低いクライアントを操作する場合に非常に役立ちます(特にクエリで役立ちます)。コマンドを送信する場合は、キューを使用する方がよい場合がありますが、これはICommandHandler<TCommand>インターフェイスのデコレータとして実装することもできます。

これらの概念を説明するいくつかの記事は次のとおりです。

于 2013-01-30T16:26:15.020 に答える
3

static BootStrapおそらく、各レイヤー内にメソッドを実装して、登録の呼び出しをチェーン化する(コンテナインスタンスを各メソッドに渡す)ことを試みることができます。

Wpf.Client呼び出すWpf.Service.Bootstrap(container)呼び出しWPF.Bll.Bootstrap(container)...?

これでうまくいくはずですが、Stevensの記事を読むことを心からお勧めします。これらの記事は非常に理にかなっており、実装すると非常に柔軟なアーキテクチャを提供します。

于 2013-01-30T18:10:28.183 に答える