Reputation: 1607
I have a function which make repository Dictionary, of multiple tables at run time, What i want is make this as generic, but I am stuck on this error..
public IRepository<TEntity> GetRepository<TEntity>(string TypeName) where TEntity : class
{
Type t = GetInstance(TypeName);
if (_repositories.Keys.Contains(t))
{
return _repositories[t] as IRepository<TEntity>;
}
var repository = new Repository<TEntity>(_context);
_repositories.Add(t, repository);
return repository;
}
When I call this function as
string tn = tt.GetType().FullName;
Type tttt = GetInstance(tn);
uu.GetRepository<Object>(tn).Add(tt);
it throws Exception
The entity type Object is not part of the model for the current context.
how can I make this happen as
string tn = tt.GetType().FullName;
Type tttt = GetInstance(tn);
uu.GetRepository<typeof(tt)>(tn).Add(tt);
or something type else.
Upvotes: 1
Views: 1010
Reputation: 101453
If you just want to know how to do it in principle (if ignore questions about should you do that at all or not), then here is how:
string tn = tt.GetType().FullName;
// get reference to GetRepository<TEntity>
var genericGet = uu.GetType().GetMethod("GetRepository").MakeGenericMethod(tt.GetType());
// invoke to get IRepository<TEntity>
var repository = genericGet.Invoke(uu, new object[] { tn});
// get IRepository<TEntity>.Add
var addMethod = repository.GetType().GetMethod("Add");
// invoke
addMethod.Invoke(repository, new object[] { tt});
If you would go this way - better make your Add
methods accept object instead of generic type argument, and so make your interface just IRepository
, not IRepository<T>
. Then inside repository - get reference to specific DbSet
and Add
method using technique above.
Upvotes: 1
Reputation: 7671
If you want it to be generic, you need to specify a type as a generic parameter. The client code must know the type, not just have an instance of that type.
In your case, using Object
as a generic type argument does not make sense, because that would not provide the type inference for the underlying framework. That is the reason for the exception thrown.
Also, at runtime, if your solution is multithreaded, you can't use Dictionary without extra synchronization. For your task, I'd recommend ConcurrentDictionary.
void Main()
{
var repository = GetRepository<MyEntity1>();
MyEntity1 instance = repository.Get(1);
}
class MyEntity1
{
}
ConcurrentDictionary<Type, object> repositories = new ConcurrentDictionary<System.Type, object>();
interface IRepository<T>
{
T Get(int id);
}
class Repository<T> : IRepository<T> where T:new()
{
public T Get(int id)
{
return new T();
}
}
IRepository<T> GetRepository<T>() where T:new()
{
return (IRepository<T>)repositories.GetOrAdd(typeof(T), t => new Repository<T>());
}
Upvotes: 1