I have the following generic method inside my class that works as a repository pattern:
public DbSet<T> GetAll<T>() where T : class
{
return dbContext.Set<T>();
}
Now, i would like to get a list of all entities in the database that belong to an entity class that implements a specific interface ( IChangeTrackingEntity
). So currently there are around 10 specific tables/classes that conform to this, but i don't want to add 10 hardcoded calls to these tables, so I would like to do it using reflection instead (it might also be that the classes that implement this interface change in the future and I don't want to have to remember to change here as well and make the code dependant on each other).
Example of code that works, but that i don't want:
var result = new List<IChangeTrackingEntity>();
using ( var repository = new DbRepository())
{
result.AddRange( repository.GetAll<FirstTypeThatImplementsInterface>() );
result.AddRange( repository.GetAll<SecondTypeThatImplementsInterface>() );
result.AddRange( repository.GetAll<ThirdTypeThatImplementsInterface>() );
result.AddRange( repository.GetAll<FourthTypeThatImplementsInterface>() );
result.AddRange( repository.GetAll<FifthTypeThatImplementsInterface>() );
}
return result;
I am quite close, but I can't get the last part to work of casting the result of the Invoke
back to the correct type. Waht i got currently is this:
var result = new List<IChangeTrackingEntity>();
var method = typeof (DbRepository).GetMethod("GetAll");
using ( var repository = new DbRepository())
{
foreach (var p in typeof(AnchorDbContext).GetProperties())
{
if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
{
var pType = p.PropertyType.GetGenericArguments()[0];
if (pType.GetInterface("IChangeTrackingEntity") != null)
{
var genericMethod = method.MakeGenericMethod(new[] {pType});
result.AddRange(genericMethod.Invoke(repository, null) as DbSet<IChangeTrackingEntity>);
}
}
}
return result;
}
The problem above it that the Invoke call return a object
and I need to cast it to basically DbSet<pType>
.
In my current code genericMethod.Invoke(repository, null) as DbSet<IChangeTrackingEntity>
returns null
indicating that I can't cast the return value as I want, so I need the specific return value type and not the interface I think.
Any idea of how to accomplish this?
Try casting to IEnumerable<IChangeTrackingEntity>
. This should work due to co/contravariance.
I don't know much about this specific issue, but you seem to be casting from DbSet<T> where T : IChangeTrackingEntity
to DbSet<IChangeTrackingEntity>
. This is called covariance or contravariance (I always get confused between them...) and it only works if DbSet<>
is an interface. So, casting won't work here. Use an equivalent interface if you can, or make a generic method that accepts DbSet where T: IChangeTrackingEntity
and returns DbSet<IChangeTrackingEntity>
somehow. I'll try to work out how to do that, and post an answer, if no one has answered before me (unlikely on this site :P)
I'm thinking you need to see this question :
MethodInfo method = typeof(Sample).GetMethod("GenericMethod");
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.