在实体框架的更改跟踪器中处理通用实体

问题描述 投票:0回答:1

我正在实现领域驱动设计 (DDD) 架构,并希望为我的实体利用强类型 ID。我的基础

AggregateRoot
类看起来像这样:

public abstract class AggregateRoot<TId>
    : Entity<TId>
    where TId : struct
{
    private readonly List<IDomainEvent> _domainEvents = [];

    // ...
}

这是一个示例实体:

public readonly record struct AuctionId(Guid Value);

public class Auction
    : AggregateRoot<AuctionId>
{
    // ...
}

我有一个域事件调度程序拦截器(

PublishDomainEventsInterceptor
),我希望它可以与所有聚合一起工作:

internal sealed class PublishDomainEventsInterceptor 
    : SaveChangesInterceptor 
{
    // ...

    public async Task PublishDomainEvents(
        DbContext? context)
    {
        // ...

        // Problem: Need a generic way to handle strongly-typed IDs here
        var entities = context.ChangeTracker
            .Entries<AggregateRoot>() // Issue: Requires type argument
            .Where(e => e.Entity.DomainEvents.Any())
            .Select(e => e.Entity); 

        // ...
    }
}

如何在事先不知道具体

PublishDomainEvents()
类型的情况下修改我的
AggregateRoot<TId>
方法或相关方法以使其与
TId
一起使用?我想保持类型安全和强类型 ID 的好处。

提前感谢您的帮助,干杯! :)

c# entity-framework-core domain-driven-design
1个回答
2
投票

由于您的拦截器代码实际上不需要使用强类型 Id,最简单的选择是引入一个非通用接口来实现和使用它:

AggregateRoot<TId>

及用法:

public interface IAggregateRoot { public IEnumerable<IDomainEvent> DomainEvents { get; } } public abstract class AggregateRoot<TId> : Entity<TId>, IAggregateRoot where TId : struct { // ... }

© www.soinside.com 2019 - 2024. All rights reserved.