2011-09-14 8 views
8
の制約に違反しています

私は本質的に次のように呼び出される汎用リポジトリファクトリを実装しようとしています。Generics&Reflection - GenericArguments [0]はタイプ

var resposFactory = new RepositoryFactory<IRepository<Document>>(); 

リポジトリ工場、次のようになります。

public class RepositoryFactory<T> : IRepositoryFactory<T> 
{ 
    public T GetRepository(Guid listGuid, 
     IEnumerable<FieldToEntityPropertyMapper> fieldMappings) 
    { 
     Assembly callingAssembly = Assembly.GetExecutingAssembly(); 

     Type[] typesInThisAssembly = callingAssembly.GetTypes(); 

     Type genericBase = typeof (T).GetGenericTypeDefinition(); 

     Type tempType = (
      from type in typesInThisAssembly 
      from intface in type.GetInterfaces() 
      where intface.IsGenericType 
      where intface.GetGenericTypeDefinition() == genericBase 
      where type.GetConstructor(Type.EmptyTypes) != null 
      select type) 
      .FirstOrDefault(); 

     if (tempType != null) 
     { 
      Type newType = tempType.MakeGenericType(typeof(T)); 

      ConstructorInfo[] c = newType.GetConstructors(); 

      return (T)c[0].Invoke(new object[] { listGuid, fieldMappings }); 
     } 
    } 
} 

私はGetRespositoryを呼び出すしようとするには、次の行が

Type newType = tempType.MakeGenericType(typeof(T)); 
を失敗した機能します

私が手にエラーがある:

ArgumentExceptionが - Framework.Repositories.DocumentLibraryRepository`1」に関するGenericArguments [0]、 'Framework.Repositories.IRepository`1 [Apps.Documents.Entities.PerpetualDocument]'、 [T] 'は型' T 'の制約に違反します。

ここで何が問題になっているかについてのアイデアはありますか?

EDIT:

次のようにリポジトリの実装は次のとおりです。

public class DocumentLibraryRepository<T> : IRepository<T> 
               where T : class, new() 
{ 
    public DocumentLibraryRepository(Guid listGuid, IEnumerable<IFieldToEntityPropertyMapper> fieldMappings) 
    { 
     ... 
    } 

    ... 
} 

などIRepositoryに見える:あなたのコードはDocumentLibraryRepository<IRepository<Document>>の代わりのインスタンスを作成しようと

public interface IRepository<T> where T : class 
    { 
     void Add(T entity); 
     void Remove(T entity); 
     void Update(T entity); 
     T FindById(int entityId); 
     IEnumerable<T> Find(string camlQuery); 
     IEnumerable<T> All(); 
    } 
+0

返品明細書がありませんか?あなたはそのメソッドの完全なコピーを貼り付けましたか? –

+0

また、パラメータを使用してコンストラクタを明示的に呼び出そうとしているときに、パラメータを持たないコンストラクタが存在するかどうかチェックするのはなぜですか?パラメータのないコンストラクタを使用している場合、 'GetConstructors'によって返される0番目のコンストラクタになる可能性が最も高くなります。この場合、* with *パラメータを呼び出すと失敗します。 –

+0

はいごめんなさい。「デフォルトを返す(T)」は最後にする必要があります。 – Bevan

答えて

6

DocumentLibraryRepository<Document>

あなたが代わりにこのコードを使用する:

var genericArgument = typeof(T).GetGenericArguments().FirstOrDefault(); 
if (tempType != null && genericArgument != null) 
{ 
    Type newType = tempType.MakeGenericType(genericArgument); 
+0

申し訳ありません。追加する必要があります。 パブリックインターフェイスIRepository T:クラス { void Add(Tエンティティ); void(Tエンティティ)を削除します。 void Update(Tエンティティ)。 T FindById(int entityId); IEnumerable Find(文字列camlQuery); IEnumerable All(); } – Bevan

+0

@ベヴァン:OK。私の更新された答えを見てください。これはあなたの問題を解決するはずです。 –

+0

ありがとう、それはトリックでした!あなたは命の恩人です:) – Bevan

0

これはおそらく、あなたがジェネリック型DocumentLibraryRepository<T>where制約を使用したことやタイプPerpetualDocumentはその制約

0

に一致していないことを示唆していますたぶん私の答えは、同じエラーを持つ人を助けることができます。 私のシナリオは次のとおりです。

public class B 
{ 
    public string Name; 
} 

public class A 
{ 
    public EventHandler<B> TypedEvent; 

    public void MyMethod(B item) 
    { 
     if (TypedEvent != null) 
     { 
      TypedEvent(null, item); 
     } 
    } 
} 

public class T 
{ 
    public void Run() 
    { 
     A item = new A(); 
     item.TypedEvent += new EventHandler<B>(ItemEvent); 
    } 

    private void ItemEvent(object sender, B b) 
    { 
     b.Name = "Loaded"; 
    } 
} 

ので、実行時にファイル名を指定して実行()メソッドがロードされたときに(実行されません)私は例外を取得: GenericArguments [0] .... System.EventHandler`1 [TEventArgs]」違反メソッドRun()の型パラメータ 'TEventArgs'の制約。

私はそれが.NETのバグかどうかわかりませんが、私の場合、AクラスのTypedEventプロパティのタイプをEventHandlerにタイプしたEventHandler<B>から変更しました。 私のシナリオは:

public class B 
{ 
    public string Name; 
} 

public class A 
{ 
    public EventHandler TypedEvent; 

    public void MyMethod(B item) 
    { 
     if (TypedEvent != null) 
     { 
      TypedEvent(item, null); 
     } 
    } 
} 

public class T 
{ 
    public void Run() 
    { 
     A item = new A(); 
     item.TypedEvent += new EventHandler(ItemEvent); 
    } 

    private void ItemEvent(object sender, EventArgs e) 
    { 
     B b = sender as B; 
     b.Name = "Loaded"; 
    } 
} 

私は誰かを助けることを願っています。