I am passing a string of the name of the entity type I want to query and getting the type based on the string. I want to get the DbSet
back and return an IQueryable
. The problem is where I am doing (DbSet<tableEntity>)
and getting the following error:
tableEntity is a variable but used like a type
when trying to cast. Is there a way to resolve this?
public object GetList(string tableEntity)
{
Type tableEntity = Type.GetType("TestProject." + typeName + ", TestProject");
var dbObject = (DbSet<tableEntity>)typeof(DbContext).GetMethod("Set", Type.EmptyTypes)
.MakeGenericMethod(tableEntity)
.Invoke(databaseContext, null);
return dbObject.AsQueryable();
}
EDIT
Just to add I don't have access to the type that's we I am passing the name through a string.
So it turns out that the entity type is literally not known, or knowable, at compile time. It has to be a string.
The only place you're using the type at compile time is in the cast to (DbSet<tableEntity>)
. Well, you may not need that. All you need from that type is to call AsQueryable()
, and AsQueryable()
is an extension method for IEnumerable
, with generic and non-generic versions. IF we call it through non-generic IEnumerable
, that's non-generic AsQueryable()
, returning non-generic IQueryable
. But we're returning object
anyway, so hey. For the result of this thing to be useful, something somewhere must be doing a fair amount of reflection on it anyway, so the declared type is likely to be of little consequence.
See if this works:
public object GetList(string typeName)
{
Type tableEntity = Type.GetType("TestProject." + typeName + ", TestProject");
var dbObject = (System.Collections.IEnumerable)
typeof(DbContext).GetMethod("Set", Type.EmptyTypes)
.MakeGenericMethod(tableEntity)
.Invoke(databaseContext, null);
return dbObject.AsQueryable();
}
If it turns out you need generic IQueryable<TEntityType>
, we'll have to use reflection to get MethodInfo
for AsQueryable<TEntityType>
for the unknown (at compile time) entity type, and call MakeGenericMethod(tableEntity)
on that.
First try:
In the language, type parameters to generics must be actual types, not instances of the Type
class. That's because they're resolved at compile time.
But that's no problem; to pass a type parameter to a generic method, simply write a generic method with a type parameter.
You can't do this:
var stuff = GetList("MyTableEntityClass");
But this is just as good:
var stuff = GetList<MyTableEntityClass>();
...
public object GetList<TTableEntity>()
{
var dbObject = (DbSet<TTableEntity>)typeof(DbContext)
.GetMethod("Set", Type.EmptyTypes)
.MakeGenericMethod(typeof(TTableEntity))
.Invoke(databaseContext, null);
return dbObject.AsQueryable();
}
Reflection is different; that's why we pass typeof(TTableEntity)
to MakeGenericMethod()
.
And once we're using an actual type that the compiler can check, we can do better with our return type, too:
public IQueryable<TTableEntity> GetList<TTableEntity>()
{
var dbObject = (DbSet<TTableEntity>)typeof(DbContext)
.GetMethod("Set", Type.EmptyTypes)
.MakeGenericMethod(typeof(TTableEntity))
.Invoke(databaseContext, null);
return dbObject.AsQueryable();
}
Since, as Ed mentioned, you don't use the table entity type at compile time, why not just use the non-generic databaseContext.Set (tableEntity).AsQueryable ()
? But if you've set your heart on Set<>
, try this:
public object GetList(string tableEntity)
{
Type tableEntity = Type.GetType("TestProject." + typeName + ", TestProject");
return GetType ()
.GetMethod ("GetListHelper")
.MakeGenericMethod (tableEntity)
.Invoke (this) ;
}
public object GetListHelper<T> () where T : class
{
var dbObject = databaseContext.Set<T> (null) ;
return dbObject.AsQueryable();
}