Ich verwende .NET Core 2.1 mit EntityFramework Core.
In meinem Projekt sind verschiedene Modelle / Entitäten / Typen definiert. zB Schüler, Klasse, Lehrer.
Ich erhalte die Tabellendaten für diese Modelle in meinem Cache.
Im Moment mache ich das;
string[] tablesToBeCached = { "Student", "Class", "Teacher" };
foreach(var table in tablesToBeCached)
{
cache.Set(key, GetTableData(dbContext, table));
}
und die Funktion GetTableData () ist wie folgt definiert;
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;
}
}
Ich möchte, dass dieser Code intelligent und kurz ist.
Ich habe versucht zu folgen, aber es hat nicht funktioniert. (Der Fehler ist, dass 'x' eine Variable ist, aber wie ein Typ verwendet wird.)
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>();
}
Kann jemand bitte helfen? Ist das überhaupt in C # möglich?
Wie jemand in den Kommentaren betonte, sollten Sie sich für Generika entscheiden:
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>();
}
Um zu vermeiden, dass für cache.Set
Entität derselbe Code ( cache.Set
) geschrieben wird, können Sie Reflection verwenden, Ihre Entitäten sollten jedoch eine Art Common Interface oder Basisklasse implementieren.
Angenommen, Ihre Entitäten implementieren eine Common Interface IEntity
:
interface IEntity {}
class Student: IEntity {}
class Teacher: IEntity {}
dann kannst du
1 Rufen Sie alle Typen ab, die IEntity implementieren:
var type = typeof(IEntity);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
2 Rufen Sie die GetTableData-Methode folgendermaßen auf:
MethodInfo method = GetType.GetMethod("GetTableData ");
foreach (var entityType in types)
{
MethodInfo genericMethod = method.MakeGenericMethod(entityType);
genericMethod.Invoke(this, null);
}
Ich habe eine sehr ähnliche Lösung implementiert, wie @Alberto geantwortet hat (aber ich habe das IEntity-Schnittstellenbit vermieden). Besonderer Dank geht an @ gunr2171 für den Hinweis in die richtige Richtung. Meine Lösung ist wie folgt;
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>();
}