Faraz Ahmed
Faraz Ahmed

Reputation: 1607

Make generic Type on function as Generic Object

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

Answers (2)

Evk
Evk

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

George Polevoy
George Polevoy

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

Related Questions