Based on [the difference between Type.IsGenericType
and Type.IsGenericTypeDefinition
][1], I gained the piece of information I was missing in order to be able to retrieve a DbContext's DbSets via Reflection.
However, I am now stuck somewhere else. In the code sample below, I do succeed in obtaining the DbSet generic instances, but I now want to be able to cast them at compile time, to the specific generic type defintion.
dbSet is a real instance of one of the DbSets<...> from my DbContext, but how to cast it to its real type definition ? (Take the 1st loop iteration, dBSet will represent DbSet - how to enforce this type at compile time upon this variable ?
Update: I have just reviewed what I am trying to do and... am afraid it makes no sense/it is not possible. Since the real types are discovered only at runtime, there is no way I can, prior to that (and compile time is a stage in time prior to that) relate to the real generic types.
In any case - what I am really interested to is to have, at compile time, the IDE showing me members of IEnumerable<T>
(DbSet<> implements it). So I really need to cast it to DbSet<>
. How does such a cast should look like ?
Is it possible ?!
private static void Main(string[] args)
{
MyDb myDb = new MyDb();
List<PropertyInfo> dbSetProperties = myDb
.GetType()
.GetProperties()
.Where(pi => pi.PropertyType.IsGenericType && string.Equals(pi.PropertyType.GetGenericTypeDefinition().FullName, typeof(DbSet<>).FullName, StringComparison.OrdinalIgnoreCase)).ToList();
foreach (PropertyInfo dbSetProperty in dbSetProperties)
{
Type[] typeArguments = dbSetProperty.PropertyType.GetGenericArguments();
Type dbSetGenericContainer = typeof(DbSet<>);
Type dbSetGenericType = dbSetGenericContainer.MakeGenericType(typeArguments);
object dbSet = Convert.ChangeType(dbSetProperty.GetValue(myDb), dbSetGenericType);
}
}
public class MyDb : DbContext
{
public DbSet<A> A { get; set; }
public DbSet<B> B { get; set; }
public void ClearTables()
{
}
}
public class A
{
public string aaa { get; set; }
public List<int> myList { get; set; }
}
public class B
{
public int MyInt { get; set; }
}