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();
}
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.
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.
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.
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);
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With