2013-06-20 5 views
1

есть класссоздать общий класс для имени типа

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

как создать его, зная только имя TEntity?

Пример:

класс игры { }

строка nameEntity = "Игра";

var repository = новый репозиторий < long, ???>();

+1

проверить этот вопрос http://stackoverflow.com/questions/493490/converting-a-string-to-a-class-name –

+0

Тип type = Тип.GetType (имя_подстановки); Тип entity = typeof (DBCloud.Repositories.Repository <>).MakeGenericType (новый тип [] {type}); var rep = Activator.CreateInstance (entity); Ошибка \t 1 Использование репозитория типа типа 'требует двух аргументов типа – ask125342

ответ

2

Там три части к этому:

  • приобретающие Type из строки "Game"
  • создает общий экземпляр
  • делать что-то полезное с ним

Первый относительно легко, если вы знаете немного больше - например, что Game находится в конкретную сборку и пространство имен. Если вы знаете, некоторые фиксированного типа в этой сборке, вы можете использовать:

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

(и проверить его не возвращает null)

Затем нам нужно создать общий тип:

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

однако, обратите внимание, что это object. Было бы более удобно, если бы был не общий интерфейс или базовый класс, который вы могли бы использовать для Repository<,> - я бы поставил серьезным, хотя и добавлял один!

Для использования, что самый простой подход здесь будет dynamic:

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

и использовать необщего IList API. Если dynamic не является вариантом, вам придется использовать отражение.

Кроме того, добавление необщего API сделает этот тривиальный:

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

, то это просто:

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

Примечание: в зависимости от данных, IList может не работать - вы могли бы необходимо вместо этого отказаться от не общего IEnumerable.

+0

Невозможно неявно преобразовать тип' System.Collections.Generic.ICollection 'в' System.Collections.IList '. Явное преобразование существует (вы пропускаете листинг?) – ask125342

+0

Извините, это работает, спасибо! – ask125342

Смежные вопросы