Reputation: 6449
I have an application logging a list of query to be executed at a later time. So I have a list containing something like this:
class QueryToBeExecutedLater
{
string sql { get; set; }
object[] parameters { get; set; }
string entityTypeFullName { get; set; }
}
And I need to execute them like:
List<QueryToBeExecutedLater> allQueries = ...
foreach(var q in allQueries )
{
Type elementType = Type.GetType(q.entityTypeFullName);
var result = await db.Set<elementType>.FromSqlRaw(q.sql,q.parameters).ToListAsync();
}
But of course it doesn't work.
I am not all that familiar with reflection. So far I have been able to get the dbSet with this:
List<QueryToBeExecutedLater> allQueries = ...
foreach(var q in allQueries )
{
Type elementType = Type.GetType(q.entityTypeFullName);
MethodInfo method = typeof(myDbContext).GetMethod("Set",
BindingFlags.Public | BindingFlags.Static);
method = method.MakeGenericMethod(elementType);
var _dbSet = method.Invoke(db,null);
var result = _dbSet.FromSqlRaw(q.sql,q.parameters);
}
Which of course doesn't work, because:
I probably should be doing something like this:
List<QueryToBeExecutedLater> allQueries = ...
foreach(var q in allQueries )
{
Type elementType = Type.GetType(q.entityTypeFullName);
MethodInfo method = typeof(myDbContext).GetMethod("Set",
BindingFlags.Public | BindingFlags.Static);
method = method.MakeGenericMethod(elementType);
var _dbSet = method.Invoke(db,null);
var typeReturnedByInvoke_type_of_dbset = **...How Do I Get this type?...**
MethodInfo _method = typeReturnedByInvoke_type_of_dbset.GetMethod("FromSqlRaw",
BindingFlags.Public | BindingFlags.Static);
object[] frontParameter = { sql };
var allParameters = frontParameter.Concat(parameters).ToArray();
// The "null" is because it's a static method
var result = _method.Invoke(_dbSet, allParameters);
}
But how do I get the type of the result of method.Invoke
?
Or is there a way to avoid all these invokes and just cast the result of the first invoke to the right DbSet<elementType>
and continue from there without reflection?
Thank you in advance for any help!
Upvotes: 1
Views: 1923
Reputation: 89361
You've figured out how to call a single generic method through reflection, and that's all you need. Just introduce a RunQuery<TEntity>
and call that.
EG
public static List<object> RunQuery(QuerySpec query, DbContext db)
{
Type elementType = Type.GetType(query.entityTypeFullName);
var rv = typeof(Program).GetMethod("RunQuery2", BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(elementType)
.Invoke(null, new object[] { query, db });
return (List<Object>)rv;
}
private static List<object> RunQuery2<T>(QuerySpec query, DbContext db) where T : class
{
var rv = db.Set<T>().FromSqlRaw(query.sql, query.parameters)
.Select( e=>(object)e )
.ToList();
return rv;
}
Upvotes: 5