我的许多数据模型都使用此接口:
public interface IHasPrimaryImageProperty
{
PrimaryImageDataModel PrimaryImage { get; set; }
int? PrimaryImageId { get; set; }
}
PrimaryImageDataModel
在哪里:
public class PrimaryImageDataModel
{
public int Id { get; set; }
public string ImageFile { get; set; }
public int TotalItemsUsingImage { get; set; }
}
我想通过对实现PrimaryImageDataModel.TotalItemsUsingImage
的所有数据模型进行计数来填充IHasPrimaryImageProperty
。
到目前为止,我已经设法获得实现IHasPrimaryImageProperty
的类型的列表。
但是我无法获得每种类型的总数。
请参见下面的示例,以演示我想要实现的目标。
public static PrimaryImageDataModel GetImageUsageTotals(PrimaryImageDataModel image)
{
var typesUsingImage = GetTypesWithPrimaryImageProperty();
int totalUsingImage = 0;
foreach (Type typeUsingImage in typesUsingImage)
{
// I WOULD LIKE TO DO SOMETHING LIKE THIS
totalForType = db.Set<typeUsingImage>()
.Where(x => x.PrimaryImageId == image.Id)
.Count()
totalUsingImage += totalForType;
}
image.TotalItemsUsingImage = totalUsingImage;
return image;
}
public static IEnumerable<Type> GetTypesWithPrimaryImageProperty()
{
var currentAssembly = Assembly.GetExecutingAssembly();
foreach (Type type in currentAssembly.GetTypes())
{
if (type.GetInterfaces().Contains(typeof(IHasPrimaryImageProperty)))
{
yield return type;
}
}
}
答案 0 :(得分:2)
我看到的最简单的方法(在EF6和EF Core中均可使用)是创建一个通用方法并通过反射对其进行调用。
例如:
static int CountUsage<T>(DbContext db, PrimaryImageDataModel image)
where T : class, IHasPrimaryImageProperty
{
return db.Set<T>()
.Where(x => x.PrimaryImageId == image.Id)
.Count();
}
static readonly MethodInfo CountUsageMethodInfo = typeof(YourClass)
.GetMethod("CountUsage", BindingFlags.NonPublic | BindingFlags.Static);
public static PrimaryImageDataModel GetImageUsageTotals(PrimaryImageDataModel image)
{
var args = new object[] { db, image };
image.TotalItemsUsingImage = GetTypesWithPrimaryImageProperty()
.Sum(type => (int)CountUsageMethodInfo.MakeGenericMethod(type).Invoke(null, args));
return image;
}
答案 1 :(得分:1)
IQueryable是协变的。请参见Variance in Generic Interfaces (C#),对于由该Entity类型实现的接口,这允许将IQueryable<SomeEntity>
强制转换为IQueryable<InterfaceType>
。
因此,如果将此方法放在EF6 DbContext类型上:
public IQueryable<T> GetQuery<T>(Type EntityType)
{
return (IQueryable<T>)this.Set(EntityType);
}
或者对于EF Core来说是这样的:
public IQueryable<T> GetQuery<T>(Type EntityType)
{
var pq = from p in this.GetType().GetProperties()
where p.PropertyType.IsGenericType
&& p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)
&& p.PropertyType.GenericTypeArguments[0] == EntityType
select p;
var prop = pq.Single();
return (IQueryable<T>)prop.GetValue(this);
}
那你就可以写
foreach (Type typeUsingImage in typesUsingImage)
{
// I WOULD LIKE TO DO SOMETHING LIKE THIS
totalForType = db.GetQuery<IHasPrimaryImageProperty>(typeUsingImage)
.Where(x => x.PrimaryImageId == image.Id)
.Count()
totalUsingImage += totalForType;
}