Передача типов для работы в c # - PullRequest
0 голосов
/ 20 сентября 2019

Я использую .net core 2.1 с ядром entityframework.

У меня есть разные модели / сущности / типы, определенные в моем проекте.например, ученик, класс, учитель.

Я получаю данные таблиц для этих моделей для установки в моем кэше.

В данный момент я делаю это;

string[] tablesToBeCached  = { "Student", "Class", "Teacher" };

foreach(var table in tablesToBeCached)
{
     cache.Set(key, GetTableData(dbContext, table));
}

и функция GetTableData () определяется следующим образом:

public IEnumerable<object> GetTableData(DBContext dbContext, string tableName)
{
      switch (tableName)
      {
          case "Student":
              return dbContext.Student;

          case "Class":
              return dbContext.Class;

          case "Teacher":
              return dbContext.Teacher;

          default:
              return null;
       }
  }

Я хочу, чтобы этот код был умным и коротким.

Я пытался следовать, но не работал;(Ошибка 'x' является переменной, но используется как тип)

List<object> entities = new List<object> { typeof(Student), typeof(Class), typeof(Teacher) };
entities.ForEach(x => GetTableData(x, dbContext));

public IEnumerable<object> GetTableData(object x, DBContext dbContext)
{
     return dbContext.Set<x>();
}

Может кто-нибудь помочь?Это вообще возможно в C #?

Ответы [ 2 ]

1 голос
/ 20 сентября 2019

Как кто-то указал в комментариях, вы должны идти с обобщениями:

cache.Set(key1, GetTableData<Student>(dbContext));
cache.Set(key2, GetTableData<Class>(dbContext));
cache.Set(key3, GetTableData<Teacher>(dbContext));


public static IEnumerable<T> GetTableData<T> (DBContext dbContext)
{
     return dbContext.Set<T>();
}

Чтобы избежать написания того же кода (cache.Set) для каждой сущности, вы можете использовать отражение, но ваши сущности должны реализоватькакой-то общий интерфейс или базовый класс.

Например, предположим, что ваши сущности реализуют общий интерфейс IEntity:

interface IEntity {}

class Student: IEntity {}

class Teacher: IEntity {}

, тогда вы можете

1 получить всетипы, которые реализуют IEntity:

var type = typeof(IEntity);
var types = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => type.IsAssignableFrom(p));

2, вызывают метод GetTableData следующим образом:

MethodInfo method = GetType.GetMethod("GetTableData ");

foreach (var entityType in types)
{
    MethodInfo genericMethod = method.MakeGenericMethod(entityType);
    genericMethod.Invoke(this, null);
}
0 голосов
/ 23 сентября 2019

Я реализовал очень похожее решение, как ответил @Alberto (но я избежал бита интерфейса IEntity).Отдельное спасибо @ gunr2171 за указание в правильном направлении.Мое решение заключается в следующем:

MethodInfo methodInfo = typeof(CacheSettings).GetMethod("GetTableData");
string[] tablesToBeCached  = { "Student", "Class", "Teacher" };
object[] parameters = new object[] { myDBContextObj };

foreach(var tblToBeCached in tablesToBeCached)
{
    string key = $"{tblToBeCached}";
    MethodInfo getTableDataMethod = methodInfo.MakeGenericMethod(Type.GetType($"Namespace.{tblToBeCached}, AssemblyName"));
    cache.Set(key, getTableDataMethod.Invoke(null, parameters));
}

and the GetTableData() method is just one liner (Happy days ?)

public static IEnumerable<T> GetTableData<T>(MyDBContext dbContext) where T : class
{
   return dbContext.Set<T>();
}
...