C# 强制转换自引用实体,检测泛型类型

C# 强制转换自引用实体,检测泛型类型,c#,entity-framework,generics,asp.net-core,entity-framework-core,C#,Entity Framework,Generics,Asp.net Core,Entity Framework Core,有一次,我得到了所有实体的接口: public interface IEntity { int Id { get; set; } } 对于某些实体,将存在一个mutationtable,以记录为哪个实体(CRUD)做了什么 我在一个类上实现了接口IEntity,一些实体将继承该接口 public class Entity : IEntity { public int Id { get; set; } } 实体测试继承自实体(因为它是一个实体),并通过对自身的引用实现模拟 pu

有一次,我得到了所有实体的接口:

public interface IEntity
{
    int Id { get; set; }
}
对于某些实体,将存在一个mutationtable,以记录为哪个实体(CRUD)做了什么

我在一个类上实现了接口
IEntity
,一些实体将继承该接口

public class Entity : IEntity
{
    public int Id { get; set; }
}
实体
测试
继承自
实体
(因为它是一个实体),并通过对自身的引用实现模拟

public class Test : Entity, IMutation<Test>
{
    public ICollection<Mutation<Test>> Mutations { get; set; } = new List<Mutation<Test>>();
}
现在的问题是,我永远不知道我的类型是什么。我知道它必须来自类型
ienty
。 但是当我试图将实体解析为
IMutation
时,我得到一个错误,即他不能从
IMutation
转换为
IMutation
。(但是
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);
IEnumerable mutationEntries=
条目。选择(s=>s.Entity)。其中(
w=>
w、 GetType()
.GetInterfaces()
.任何(
x=>
x、 GetTypeInfo().IsGenericType&&x.GetGenericTypeDefinition()==typeof(IMutation)))
。选择(s=>(模拟)s);
但我已经在检查我的实体是否实现了
IMutation

也许有人有个想法,我如何解决这个问题?

很难使用非协变且没有非泛型对应项的泛型接口(如
IEnumerable
->
IEnumerable
IQueryable
->
IQueryable
等)

在这种情况下,剩下的唯一选择是反射或动态调度

例如,您可以添加如下方法:

private void ProcessMutationEntity<TEntity>(TEntity entity)
    where TEntity : IEntity, IMutation<TEntity>
{
    entity.Mutations.Add(new Mutation<TEntity> { EntityId = entity.Id, Entity = entity});
}

请将您的ProcessMutationEntity函数更改为
private void ProcessMutationEntity(TEntity entity),其中TEntity:entity,Immutation{entity.Butations.Add(new Mutation{EntityId=entity.Id,entity=entity});}
-您是个天才,伙计!它终于起作用了。你确实帮我多节省了5个小时。给你:)很高兴你帮了我的忙。干杯
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();
}
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);
private void ProcessMutationEntity<TEntity>(TEntity entity)
    where TEntity : IEntity, IMutation<TEntity>
{
    entity.Mutations.Add(new Mutation<TEntity> { EntityId = entity.Id, Entity = entity});
}
// ...
foreach (var entry in mutationEntries)
{
    ProcessMutationEntity((dynamic)entry);
}
// ...