1

次のように、他のコントラクトが拡張するベースリポジトリコントラクトがあります

public interface IBaseRepository<T> where T : class 
{
  IList<T> GetContents();
}

そしてそれを次のように拡張する他の契約があります

public interface IRepository1 : IBaseRepository<MyClass1>
{
}

public interface IRepository2 : IBaseRepository<MyClass2>
{
}

IRepository1を次のように実装します

public class Repository1 : IRepository1
{
 public IList<MyClass1> GetContents()
 {
  //some code goes here
 }
} 

IRepository2についても同様です

public class Repository2 : IRepository2
{
 public IList<MyClass2> GetContents()
 {
  //some code goes here
 }
} 

今、私は次のようにIServiceを実装するサービスService1を持っています

public class Service1 : IService
{


}

ここでサービスコンストラクターでベースリポジトリ(IBaseRepository)を使用し、このベースリポジトリのインスタンスを取得して、次のように使用します。

 public class Service1 : IService
 {
   private IBaseRepository<T> _baseRepository;
   public Service1(IBaseRepository<T> baseRepository)
   {
     _baseRepository = baseRepository;
   }

   public MyMethod1()
   {
      var contentsOfType1 = _baseRepository<MyClass1>.GetContents();
   }

   public MyMethod1()
   {
      var contentsOfType2 = _baseRepository<MyClass2>.GetContents();
   }
  }

これは私ができないことです。

したがって、タイプTの汎用ベースリポジトリコントラクトがあり、ベースコントラクトを拡張し、タイプTを指定する他のコントラクト(インターフェイス)があります。

これらすべてのコントラクト(ジェネリックベースコントラクトを拡張する)には、個別の実装があります。

私がやりたいのは、サービスクラスで、このジェネリック基本コントラクトをインスタンス化し、それを使用して拡張タイプ(したがって実装)を推測し、基本リポジトリのメソッドを使用することです。

したがって、基本契約が IBaseRepository<T>

延長契約は IRepository1 : IBaseRepository<MyClass1>

これはによって実装されます Repository1 : IRepository1

私はこれを私のサービスクラスで使用したい

public class service()
{
   *private IBaseRepository<T> _repo;

   public  service(IBaseRepository<T> repo)
   { 
    *_repo = repo;
   } 

   public void MyMethod()
   {

     *var x = _repo<MyClass1>.MethodFromIBaseRepository()
   }

}

ですから、私が達成したい*マークの付いた線は、私にはできません。

DIにはキャッスルウィンザーを使用しています。

助けてくれてありがとう

4

2 に答える 2

8

ジェネリック以外のリポジトリインターフェイスは使用しないでくださいIRepository<T>。それらが必要な場合は、抽象化が欠けています。

たとえば、カスタムリポジトリインターフェイスを使用する一般的な理由は、一部のリポジトリにはあるカスタムクエリがあり、他のリポジトリにはないカスタムクエリがあるためです。例えば:

public interface IEmployeeRepository : IRepository<Employee>
{
    Employee GetEmployeeOfTheMonth(int month);
}

ここでの問題は、IEmployeeRepositoryが「カスタムクエリ」に悪用されることです。カスタムクエリは、独自の(一般的な)抽象化に値します。

// Defines a query
public interface IQuery<TResult>
{
}

// Defines the handler that will execute queries
public interface IQueryHandler<TQuery, TResult>
    where TQuery : IQuery<TResult>
{
    TResult Handle(TQuery query);
}

IRepository<T>この抽象化により、派生物を作成することなく、システムにカスタムクエリを追加できます。

public class GetEmployeeOfTheMonthQuery : IQuery<Employee>
{
    [Range(1, 12)]
    public int Month { get; set; }
}

class GetEmployeeOfTheMonthHandler : IQueryHandler<GetEmployeeOfTheMonthQuery, Employee>
{
    public Employee Handle(GetEmployeeOfTheMonthQuery query)
    {
        // todo: query the database, web service, disk, what ever.
    }
}

その月の従業員を知る必要がある消費者は、次のように依存関係を取得しIQueryHandler<GetEmployeeOfTheMonthQuery, Employee>てクエリを実行できるようになりました。

var query = new GetEmployeeOfTheMonthQuery { Month = 11 };
var employee = this.employeeOfMonthHandler.Handle(query);

これはオーバーヘッドのように見えるかもしれませんが、このモデルは非常に柔軟でスケーラブルであり、多くの興味深い利点があります。たとえば、ハンドラーをデコレーターでラップすることにより、横断的関心事を追加するのは非常に簡単です。

これにより、リポジトリを1つの汎用インターフェイスの背後に隠すことができるため、一度に簡単にバッチ登録して、デコレータを追加することもできます。

詳細については、次の記事を参照してください。一方、私のアーキテクチャのクエリ側で

于 2012-10-16T15:16:48.790 に答える
0

ありえない。制御の反転はコンストラクターを介して依存関係を提供するため、コンストラクターで取得するタイプを知る必要があります。したがって、これを行う必要があります。

public class service()
{
   private IBaseRepository<MyClass1> _repo;

   public  service(IBaseRepository<MyClass1> repo)
   { 
       _repo = repo;
   } 

   public void MyMethod()
   {

      var x = _repo.MethodFromIBaseRepository()
   }

}
于 2012-10-16T05:34:33.283 に答える