简体   繁体   中英

create a generic class for the type name

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, >();

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM