2011-09-14 35 views
8

Tôi đã kéo tóc ra một lúc, về cơ bản tôi đang cố gắng triển khai nhà máy kho chung, được gọi như sau:Generics & Reflection - GenericArguments [0] vi phạm ràng buộc kiểu

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

nhà máy kho trông giống như sau:

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 }); 
     } 
    } 
} 

Khi tôi cố gắng gọi GetRespository hoạt dòng sau thất bại

Type newType = tempType.MakeGenericType(typeof(T)); 

Các lỗi tôi nhận được là:

ArgumentException - GenericArguments [0], 'Framework.Repositories.IRepository`1 [Apps.Documents.Entities.PerpetualDocument]', vào 'Framework.Repositories.DocumentLibraryRepository`1 [T] 'vi phạm ràng buộc của loại' T '.

Mọi ý tưởng về những gì xảy ra ở đây?

EDIT:

Việc thực hiện các kho lưu trữ như sau:

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

    ... 
} 

Và IRepository trông giống như:

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

Bạn có thiếu câu lệnh trả lại ở đó không? Bạn đã dán một bản sao đầy đủ của phương pháp đó chưa? –

+0

Ngoài ra, tại sao bạn kiểm tra sự hiện diện của một hàm tạo parameterless khi rõ ràng bạn định gọi một constructor với các tham số? Nếu bạn có một hàm tạo parameterless, nó rất có thể sẽ là hàm tạo thứ 0 được trả về bởi 'GetConstructors', trong trường hợp gọi nó là * với tham số * sẽ thất bại. –

+0

Có lỗi 'trả về mặc định (T)' nên ở cuối. – Bevan

Trả lời

6

Mã của bạn cố gắng để tạo ra một thể hiện của DocumentLibraryRepository<IRepository<Document>> thay vì DocumentLibraryRepository<Document>.

Bạn muốn sử dụng mã này để thay thế:

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

Rất tiếc, tôi phải thêm rằng: giao diện công cộng IRepository trong đó T: class { void Thêm (T thực thể); void Remove (T thực thể); void Update (thực thể T); T FindById (int entityId); IEnumerable Tìm (chuỗi camlQuery); IEnumerable All(); } – Bevan

+0

@Bevan: OK. Vui lòng xem câu trả lời cập nhật của tôi. Điều này sẽ khắc phục vấn đề của bạn. –

+0

Cảm ơn bạn rất nhiều, đã làm các trick! Bạn là người bảo vệ cuộc sống :) – Bevan

0

này sẽ đề nghị rằng có lẽ bạn đã sử dụng một hạn chế where vào loại generic DocumentLibraryRepository<T> và loại PerpetualDocument không phù hợp mà chế

0

Có lẽ câu trả lời của tôi có thể giúp ai đó có cùng lỗi. kịch bản của tôi là:

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"; 
    } 
} 

Vì vậy, trong thời gian chạy khi phương thức Run() được nạp (không thực hiện) tôi nhận được một ngoại lệ: GenericArguments [0] .... System.EventHandler`1 [TEventArgs]' Vi phạm ràng buộc của tham số kiểu 'TEventArgs' .. trên phương thức Run().

Tôi không biết đó có phải là lỗi .NET hay không. Nhưng trong trường hợp của tôi, tôi đã giải quyết vấn đề này thay đổi loại thuộc tính TypedEvent trong lớp A từ nhập EventHandler<B> thành EventHandler. Kịch bản của tôi trở thành:

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"; 
    } 
} 

Tôi hy vọng rằng có thể giúp ai đó.

Các vấn đề liên quan