2011-01-25 4 views
19

私は現在、特定のリポジトリごとに拡張されているインタフェース(IRepository<T>)を持っています:IUserRepository : IRepository<User>構造体<T>をStructureMapの実装<T>に自動的に解決します(ジェネリックタイプTのみが異なる)

これらのインターフェイスのそれぞれには、対応する具体的なクラスがあります。UserRepository : Repository<User>, IUserRepositoryです。

これらの個々のリポジトリは、追加の機能性を追加するものではありません。それらはすべて、ジェネリックスを渡すために単に使用される空のインターフェイス/クラスです。

IUserRepositoryUserRepositoryに解決するために、StructureMapを使用して、アセンブリスキャナといくつかの命名規則でレジストリを使用します。

は、私は、これは代わりにIUserRepositoryのインスタンスの周りに渡すと、それはUserRepositoryに解決得ることの、私の周りIRepository<User>を渡すことができ、それがRepository<User>に解決されている方法より最適化された状態に移動したいと思います。

これにより、余分な空のインターフェイスとクラスを作成する必要がなくなります。

私はこの一般的なマッピングを設定するためにStructureMapの設定を使用する方法を考えることができません。このような何か:

For(typeof(IRepository<>).Use(typeof(Repository<>)).WithTheGenericTypeFromTheInterfaceSuppliedAsATypeParameter(); 

編集

回答の最初のカップルを取得した後、私はこのもう少し明確にしたいです。

設定のForビットの個別のクラスを作成したくありません。私は自分のコードに次のクラス/インタフェースを持つようにしたい:

  • IRepository<T> where T : Entity
  • Repository<T> : IRepository<T> where T : Entity
  • Person : Entity
  • Product : Entity
  • Order : Entity
  • Whatever : Entity

そして大会で達成以下のマッピングがあります。

IRepository<Person> => Repository<Person> 
IRepository<Product> => Repository<Product> 
IRepository<Order> => Repository<Order> 
IRepository<Whatever> => Repository<Whatever> 

をしかし、私は、ALA、それぞれのマッピングを作成する必要がしたくないん:私はその意志単一のマッピングをしたい

For<IRepository<Person>>().Use<Repository<Person>>(); 
For<IRepository<Product>>().Use<Repository<Product>>(); 
For<IRepository<Order>>().Use<Repository<Order>>(); 
For<IRepository<Whatever>>().Use<Repository<Whatever>>(); 

すべてのIRepositoryのために働く:

For<IRepository<>>().Use<Repository<>>().WithTheSameGenericType(); 

私は、その後のサービスにリポジトリを注入するためにこれを使用します。

public MyService(IRepository<User> userRepository) 

実行時にRepository<User>に解決されると思います。

+0

あなたの目的の構成が既に本当である:あなたのケースでは

、あなただけの最後で

AddAllTypesOf(typeof(IRepository<>)); 

For<IRepository<Person>>().Use<Repository<Person>>(); For<IRepository<Product>>().Use<Repository<Product>>(); For<IRepository<Order>>().Use<Repository<Order>>(); For<IRepository<Whatever>>().Use<Repository<Whatever>>(); 

を変更する必要があり、あなたのコンテナは、のようになります。 (WithTheGenericTypeFromTheInterfaceSuppliedAsATypeParameterの必要なしに)。あなたはそれを試してもそれは仕事をしませんでしたか? –

+0

私は間違っていたに違いない - 最初はコンパイルされないので、私はジェネリック版のメソッドを使っていると思います。それらの朝のひとつ。 –

答えて

23

あなたは、呼び出すために何の空想の方法、または行うには派手な配線がない判明ただForUse(非ジェネリック版)を使用します。私はIRepository<Person>それがRepository<Person>なしとして解決されている注入

public class DataRegistry : Registry 
{ 
    public DataRegistry() 
    { 
     For(typeof (IRepository<>)).Use(typeof(Repository<>)); 
    } 
} 

w。

「リポジトリがIRepositoryのためにプラガブルでない」というエラー104が発生しました。これは、リポジトリにabstractとマークされていたためです。それを非抽象にして、そのエラーを修正し、それが望ましいものとして働いています。

+0

これは知っていいです、多くの設定を保存します。 – CRice

+0

この設定では、リポジトリ、つまりAllByLastName()の特定のメソッドをどのように追加しますか?または、IQueryableを返すだけですか? – Paul

+0

IQueryableを返すだけです。 AllByLastNameなどのドメイン固有のロジックは、サービスレイヤーに配置されます。 Repoはget、delete、query、upsertなどを持っています。 –

0

IRegistrationConventionインターフェイスをご覧ください。ここで

public class RepositoryTypeScanner : IRegistrationConvention 
{ 
    public void Process(Type type, Registry registry) 
    { 
     ... 
+0

ありがとう - しかし、それは本当に問題を解決しません。私はすでにタイプスキャナを使用していますし、命名規則を使って具体的なタイプを対応するインタフェースに配線しています。私はすべてのこれらのインターフェースと具体的な型を取り除きたいと思っています。そして、構造マップは 'IRepository 'と 'Repository 'の間でジェネリックパラメータを自動的に渡します。 –

1

例です。RepositoryTypeScannerは

public class DomainRegistry : Registry 
{ 
    public DomainRegistry() 
     : base() 
    { 
     Scan(y => 
     { 
      y.AssemblyContainingType<IRepository>(); 
      y.Assembly(Assembly.GetExecutingAssembly().FullName); 
      y.With(new RepositoryTypeScanner()); 
     }); 

。構造マップを使用すると、両方を行うこともできます。

//IRepository 
For<IMemberRepository>().Add<MemberRepository>(); 

//IRepository<T> 
For<IRepository<Member>>().Add<MemberRepository>(); 

そして、それだけで、実行時にジェネリック型を知ることによって種類を求めるために便利です。

Type repositoryType = typeof(IRepository<>).MakeGenericType(modelType); 
IocResolve.Resolve(repositoryType); 
+0

ありがとうございます - 私の質問は少し不明だと思います。私はまもなくそれを更新します。私はクラス 'MemberRepository'を作成する必要はなく、' IRepository 'を慣習にしたがって' Repository 'にマッピングするような解決策を探しています。 –

+0

あなたはこれで保存するイメージングの構成線はいくつですか?たくさんのクラスがありますか? – CRice

+0

別のリポジトリ?はい - いくつか。しかし、個々のIXXXREpositoryクラスとXXXRepositoryクラスを作成する必要はありません。なぜなら、それらは空であり、単に汎用タイプの解決に使用されるからです。エンティティの作成、インタフェースの作成、クラスの作成、レジストリの編集、そして新しいインタフェースの使用を行うよりも、エンティティを作成して 'IRepository 'を使用する方が良いでしょう。多くの作業が少なくなりました。 –

4

私はあなたがAddAllTypesOf方法を見てみることをお勧めします。私はいくつかの同様のコードを持っていて、それを使って目的を達成した。

return new Container(x => 
     { 
      x.Scan(y => 
      { 
       y.TheCallingAssembly(); 
       y.AddAllTypesOf(typeof(IRepository<>)); 
       y.WithDefaultConventions(); 
      }); 
     }); 
+0

Tyron、あなたは私の世界では非常に長期的な問題を解決しました。ありがとうございました。 –

+1

ジェネリッククラスが2つ以上のクラス(マッパーなど)に依存している場合、注意が必要です。その場合は、次の形式を使用してください: 'y.AddAllTypesOf(typeof(IMapper <,>));' – tyron

関連する問題