1

there is a class

public class Repository <TKey, TEntity>
{
    public ICollection<TEntity> Get()
    {
        using (var session = NHibernateHelper.OpenSession())
        {
            if (typeof(TEntity).IsAssignableFrom(typeof(IActualizable)))
                return session.CreateCriteria(typeof(TEntity)).Add(Restrictions.Lt("ActiveTo", DBService.GetServerTime())).List<TEntity>();

            return session.CreateCriteria(typeof(TEntity)).List<TEntity>();
        }
    }
}

how to create it, knowing only the name of TEntity?

Example:

class Game { }

string nameEntity = "Game";

var repository = new Repository< long, ??? >();

ask125342
  • 89
  • 1
  • 9
  • 1
    check this question http://stackoverflow.com/questions/493490/converting-a-string-to-a-class-name – Arie Xiao Jun 20 '13 at 07:11
  • Type type = Type.GetType(entityName); Type entity = typeof(DBCloud.Repositories.Repository<>).MakeGenericType(new Type[] { type }); var rep = Activator.CreateInstance(entity); Error 1 Using the generic type 'Repository' requires 2 type arguments – ask125342 Jun 20 '13 at 07:19

1 Answers1

2

There's three parts to this:

  • getting the Type from the string "Game"
  • creating the generic instance
  • doing something useful with it

The first is relatively easy, assuming you know a bit more - for example, that Game is in a particular assembly and namespace. If you know some fixed type in that assembly, you could use:

Type type = typeof(SomeKnownType).Assembly
      .GetType("The.Namespace." + nameEntity);

(and check it doesn't return null)

Then we need to create the generic type:

object repo = Activator.CreateInstance(
      typeof(Repository<,>).MakeGenericType(new[] {typeof(long), type}));

however, note that this is object. It would be more convenient if there was a non-generic interface or base-class that you could use for Repository<,> - I would put serious though into adding one!

To use that, the easiest approach here will be dynamic:

dynamic dynamicRepo = repo;
IList entities = dynamicRepo.Get();

and use the non-generic IList API. If dynamic isn't an option, you'd have to use reflection.

Alternatively, adding a non-generic API would make this trivial:

interface IRepository {
    IList Get();
}
public class Repository <TKey, TEntity> : IRepository {
    IList IRepository.Get() {
        return Get();
    }
    // your existing code here
}

then it is just:

var repo = (IRepository)Activator.CreateInstance(
      typeof(Repository<,>).MakeGenericType(new[] {typeof(long), type}));
IList entities = repo.Get();

Note: depending on the data, IList might not work - you might need to drop to the non-generic IEnumerable instead.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Cannot implicitly convert type 'System.Collections.Generic.ICollection' to 'System.Collections.IList'. An explicit conversion exists (are you missing a cast?) – ask125342 Jun 20 '13 at 07:38