[英]Casting of self-referencing entities, detect generic type
一次,我得到了所有实体的接口:
public interface IEntity
{
int Id { get; set; }
}
对于某些实体,将存在一个突变表以记录为哪个实体(CRUD)所做的工作
public interface IMutation<TEntity> where TEntity : IEntity
{
ICollection<Mutation<TEntity>> Mutations { get; set; }
}
对于实现IMutation
每个实体,实体框架都会创建一个名称为Mutation<EntityName>
的表。因此, Mutation<EntityName>
也是一个实体。
public class Mutation<TEntity> : Entity where TEntity : IEntity
{
public int EntityId { get; set; }
public TEntity Entity { get; set; }
}
我在一个类上实现了接口IEntity
,该类将继承某些实体。
public class Entity : IEntity
{
public int Id { get; set; }
}
实体Test
继承自Entity
(因为它是一个实体),并通过引用自身实现IMutation
public class Test : Entity, IMutation<Test>
{
public ICollection<Mutation<Test>> Mutations { get; set; } = new List<Mutation<Test>>();
}
实体框架将其获取,并创建两个表:
Id
和Name
Test
Id
(来自IEntity
的PK)和EntityId
(引用Test
IEntity
的FK)的Mutation<Test>
这一切都很好。 DB模式等等。
所以我想做的是,总是要更改一个实现IMutation<EntityName>
实体,然后创建一个新的数据集。 可以覆盖DbContext的SaveChanges
。 很好,所以我尝试了:
public override int SaveChanges()
{
IEnumerable<EntityEntry> entries = ChangeTracker.Entries(); // gets me all entries that were changed
IEnumerable<IEntity> mutationEntries =
entries.Select(s => s.Entity).Where(
w =>
w.GetType()
.GetInterfaces()
.Any(
x =>
x.GetTypeInfo().IsGenericType && x.GetGenericTypeDefinition() == typeof(IMutation<>)))
.Select(s => (IEntity)s);
// so here now I got the entries that implement IMutation<?> <-- call this now ?-type
// what I'd now want to do is:
foreach(var entry in mutationEntries)
{
IMutation<?> mutationEntry = (IMutation<?>)entry;
mutationEntry.Mutations.Add(new Mutation<?>{ /* later on, add here CRUD, Id, user who changed,... */ });
}
return base.SaveChanges();
}
现在的问题是,我不知道我的?-Type是什么。 我知道它必须来自Type IEntity
。 但是,当我尝试将Entity解析为IMutation<IEntity>
我得到一个错误,说他不能从IMutation<Test>
为IMutation<IEntity>
。 (但是Test
实现IEntity
)
尝试过这种方式:
IEnumerable<IMutation<IEntity>> mutationEntries =
entries.Select(s => s.Entity).Where(
w =>
w.GetType()
.GetInterfaces()
.Any(
x =>
x.GetTypeInfo().IsGenericType && x.GetGenericTypeDefinition() == typeof(IMutation<>)))
.Select(s => (IMutation<IEntity>)s);
但是我已经在检查我的实体是否实现IMutation
。 也许有人有主意,我该如何解决这个问题?
使用非协变且没有非通用对应项的通用接口(如IEnumerable<T>
-> IEnumerable
, IQueryable<T>
-> IQueryable
等)很难工作。
在这种情况下,唯一剩下的选择是反射或动态调度。
例如,您可以添加如下方法:
private void ProcessMutationEntity<TEntity>(TEntity entity)
where TEntity : IEntity, IMutation<TEntity>
{
entity.Mutations.Add(new Mutation<TEntity> { EntityId = entity.Id, Entity = entity});
}
然后使用DLR调用它(使用第一个示例中的代码):
// ...
foreach (var entry in mutationEntries)
{
ProcessMutationEntity((dynamic)entry);
}
// ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.