1

Ioc とジェネリック、特に私の会社がこれに関連するレイヤーをどのように設定しているかについて頭を悩ませています。私たちは MVP アーキテクチャの下で作業しています。

私は車のクラスを持っています:

class Car : ICar
{
   IList<IWheel> wheels{get;set;}
   IEngine engine{get;set;}
   string registrationplate {get;set;}

   public Car(){}
}

新しく作成された ICar を取得できるようにしたいのですが、ID で ICar を見つけられるようにしたいと考えています。問題は、私が取り組んでいるプロジェクトでいくつかの設計上の選択がなされた理由がわからないことです。すでに作成されている他のサービスの構造は次のとおりです。

私は車と車輪のサービスを持っています:

class WheelService : BaseService
{
    IWheel wheel;

    public IWheel Create()
    {
        return new wheel()
    }

 }
class CarService : BaseService
{
   WheelService wheelservice;

   public ICar CarCreate()
   {
     wheelservice = new Wheelservice()
     car = new Car();
     IWheel wheel = wheelservice.Create();
     car.wheels.add(wheel);
     return car;
   }

   public ICar Find(int id)
   {
        return (Car)base.Find<Car>(id);
   }

}
  1. まず、「エンティティごとにサービスを提供する」というのは奇妙だと思います。弱い存在にサービスがあるとは思いもしませんでした。私の考えでは、CarService の create メソッドは、ホイール サービスを呼び出さなくても、ファクトリ メソッドのように機能すると思います。
    また、ホイール サービスの create メソッドは、プレゼンター コードで実際に使用されて、IWheel を UI に戻すため、値を設定して戻すことができます。繰り返しますが、私には奇妙に思えます。プレゼンターが UI から完全な ICar オブジェクトを要求できることを意味します。

  2. Service create メソッドの依存関係は正常ですか? これは IoC を通じて導入されると考えていたでしょう。しかし、ICar の Create メソッドがすべての作成 (ホイールなどを含む) を処理する場合、コンテナにはこの特定のサービスに関連する多くのインターフェイスが含まれているのではないでしょうか?

  3. インターフェイスを導入する場合、現在具象クラスを使用している CarService.Find メソッドを調整する必要があります。これは BaseService を使用し、コンテナーとやり取りして正しいリポジトリを取得するのはこのレイヤーのみです。

class BaseService
{
private object myRepository;

 protected T GetRepository<T>(Type serviceType)
    {

        if (myRepository == null)
        {
            myRepository = (T)IoCRepositoryFactory.GetRepositoryInstance(typeof(T), serviceType);
        }
        return (T)myRepository;
     }


protected virtual IGenericRepository Repository
    {
        get
        {
            return GetRepository<IGenericRepository>(this.GetType());
        }
    }

protected virtual T Find<T>(Object id) where T : class
    {
        return (T)Repository.GetByID<T>(id);
    }

}

現在のサービス定義は具体的なクラスを使用しているため、インターフェイスのみを使用している場合、この find メソッドを呼び出す方法がわかりません。

これが長文の投稿であることをお詫びします。私はこれを 3 日間調べてきましたが、他の人が現在の設定についてどう考えているか、サービス層のドメイン オブジェクトに IOC を使用する必要があるかどうか、または現在の設定に従う必要があるかどうかを知る必要があります。現時点では、すべてが少し結びついているように感じます。

4

1 に答える 1

0

誤解されている方も多いと思います。

サービス構造から始めます。各サービスで 1 種類のエンティティのみを処理する必要はありませんが、効率を妨げない限り、問題はありません。あなたの例は不当に単純化されている可能性が高いため、将来のメンテナンスの問題なしに CarService で Wheel 管理を処理できる可能性がありますが、サービスをエンティティごとに分割するのが一般的であり、いくつかの例外が必要になることがよくありますが、通常は正常に機能します。

あなたが書いたIoCコードは、あらゆる種類の間違っています。IoC の目標は、依存関係の管理を行うすべてのコードを、邪魔にならない 1 つの場所に保持することです。コードには CarService が明示的に WheelService をインスタンス化していますが、これは IC コンテナーで処理する必要があります。また、GetRepository メソッドを使用するのは非常に厄介であり、IoC コンテナーによって自動的に処理される必要があります。

サービスとリポジトリをセットアップする 1 つの方法は次のようになります (コンストラクター インジェクションを使用している場合)。これは単なる例です (詳細な例です)。完全に理解することなく、この構造を独自のコードにコピーしないでください。

public interface IRepository {
    //Some interfaces
    //This method could only really be implemented if you are using an ORMapper like NHibernate
    public T FindById<T>(Object id) { }
}

public class BaseRepository : IRepository {
    //Some base crud methods and stuff. You can implement this if you're using an ORMapper
    public T FindById<T>(Object id) 
    { 
        return CurrentSession.FindById<T>(id);
    }
}

public class WheelRepository : BaseRepository {
    //Wheel crud

    //If you don't have an ORMapper because you're a masochist you can implement this here
    public Wheel FindById(Object id) { }
}

public class CarRepository : BaseRepository {
    //Car crud

    //If you don't have an ORMapper because you're a masochist you can implement this here
    public Car FindById(Object id) { }
}

public class BaseService {
    protected BaseRepository _baseRepository;

    //This constructor is automatically called by your IoC container when you want a BaseService
    public BaseService(BaseRepository repository)
    {
        _baseRepository = repository;
    }

    //More methods
}

public class WheelService : BaseService
{
    protected WheelRepository _wheelRepository;

    public WheelService(WheelRepository wheelRepo) : base(wheelRepo)
}

public class CarService : BaseService
{
    protected WheelService _wheelService;
    protected CarRepository _carRepository;

    public CarService(WheelService wheelService, CarRepository carRepository)
    {
        _wheelService = wheelService;
        _carRepository = carRepository;
    }
}

MVP を使用しているので、ある種の WPF/Winforms アプリを想定していますが、本当に asp.net に適合させたい場合は、Web アプリも実行できると思います。どちらの場合も、プレゼンター クラスを作成するために構成できる 1 つの Factory があります。その工場では、邪魔にならない場所ですべての注入を行う必要があり、セットアップ後に心配したり、見たりする必要さえありません。そのコードはこれを呼び出すだけです:

//Override the default factory method (just made this up)
public override Presenter GetPresenter(Type presenterType)
{
    return ComponentFactory.GetInstance(presenterType);
}

次に、サービスに依存するプレゼンターがあれば、それは自動的にそこにあり、そのサービスが必要とするものもすべてそこにあります。醜いサービス コンストラクターやファクトリー コールがどこにもないことに注意してください。すべての依存関係は、コンテナーによって自動的にセットアップされます。

あなたの会社のコードにひどい GetRepository メソッドがある理由がわかりません。通常は new Repository() のようなコンストラクター呼び出しを、わずかに保守しやすい GetRepository 呼び出しに置き換えているため、これはアンチパターンのインスタンスです。

いくつかのよく知られたコンテナーを試してみてください。Structuremapはかなり良いものです。

于 2012-08-10T08:28:47.520 に答える