Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics & Reflection - GenericArguments[0] violates the constraint of type

I've been pulling my hair out for awhile on this one, essentially I'm trying to implement a generic repository factory, which is called as follows:

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

The repository factory looks like the following:

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

When I try to call the GetRespository function the following line fails

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

The error I get is :

ArgumentException - GenericArguments[0], 'Framework.Repositories.IRepository`1[Apps.Documents.Entities.PerpetualDocument]', on 'Framework.Repositories.DocumentLibraryRepository`1[T]' violates the constraint of type 'T'.

Any ideas on what's going wrong here?

EDIT:

The implementation of the repository is as follows:

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

   ...
}

And the IRepository looks like:

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();
    }
like image 961
Bevan Avatar asked Sep 14 '11 10:09

Bevan


People also ask

What are generics used for?

In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs.

What is generics explain with an example?

Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.

What are generics and benefits?

There are many advantages to using generic collections and delegates: Type safety. Generics shift the burden of type safety from you to the compiler. There is no need to write code to test for the correct data type because it is enforced at compile time.


3 Answers

Your code tries to create an instance of DocumentLibraryRepository<IRepository<Document>> instead of DocumentLibraryRepository<Document>.

You want to use this code instead:

var genericArgument = typeof(T).GetGenericArguments().FirstOrDefault();
if (tempType != null && genericArgument != null)
{
    Type newType = tempType.MakeGenericType(genericArgument);
like image 188
Daniel Hilgarth Avatar answered Oct 19 '22 19:10

Daniel Hilgarth


This would suggest that perhaps you've used a where constraint on the generic type DocumentLibraryRepository<T> and that the type PerpetualDocument does not match that constraint

like image 32
RobV Avatar answered Oct 19 '22 21:10

RobV


I had this exactly same error, but the problem and solution was different. I had 4 Model classes, 1 base class, and only 3 of them inherited from the base, 4th did not. Once the last class inherited the base class, the error disappeared.

like image 2
Cata Hotea Avatar answered Oct 19 '22 21:10

Cata Hotea