Search code examples
asp.netasp.net-identitycqrs

How to raise event in CQRS pattern with identity for user table


I want to raise events when various identity events occur (for example, adding a user and using the userManager). I do this well for other entities but since the user entity inherits from IdentityUser I need some guidance on how to use it.

For example, one of the entities that I can use baseEntity well:

 public class Vehicle : BaseEntity
 {
  ...
 }

BaseEntity:

public abstract class BaseEntity
{
    public string Id { get; set; }

    private readonly List<BaseEvent> _domainEvents = new();

    [NotMapped]
    public IReadOnlyCollection<BaseEvent> DomainEvents => _domainEvents.AsReadOnly();

    public void AddDomainEvent(BaseEvent domainEvent)
    {
        _domainEvents.Add(domainEvent);
    }

    public void RemoveDomainEvent(BaseEvent domainEvent)
    {
        _domainEvents.Remove(domainEvent);
    }

    public void ClearDomainEvents()
    {
        _domainEvents.Clear();
    }
    
}

But in the ApplicationUser entity, I cannot use this base Entity to implement events because the applicationUser class inherits from the IdentityUser class!

    public class ApplicationUser : IdentityUser
    {

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string FatherName { get; set; }

    }

How can I use both IdentityUser and BaseEntity for events to occur in the ApplicationUser class?


Solution

  • You can Seperate them like this: An Interface For Entities that Have Id

    public interface BaseId<T> where T : class
    {
        public T Id { get; set; }
    }
    

    An Interface For Enntity With Domain Events

    public interface EntityWithDomainEvent
    {
        IReadOnlyCollection<BaseEvent> DomainEvents { get; }
        void AddDomainEvent(BaseEvent domainEvent);
        void RemoveDomainEvent(BaseEvent domainEvent);
        void ClearDomainEvents();
    }
    

    An Abstract Class To Wrap it all for other entities to get inherit from

    public abstract class BaseEntity : BaseId<string>,EntityWithDomainEvent
    {
        public string Id { get; set; }
        private readonly List<BaseEvent> _domainEvents = new();
        public IReadOnlyCollection<BaseEvent> DomainEvents => _domainEvents.AsReadOnly();
    
        public void AddDomainEvent(BaseEvent domainEvent)
        {
            _domainEvents.Add(domainEvent);
        }
    
        public void RemoveDomainEvent(BaseEvent domainEvent)
        {
            _domainEvents.Remove(domainEvent);
        }
    
        public void ClearDomainEvents()
        {
            _domainEvents.Clear();
        }
    }
    

    And Finally Your ApplicationUser

    public class ApplicationUser : IdentityUser,EntityWithDomainEvent
    {
    
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string FatherName { get; set; }
        private readonly List<BaseEvent> _domainEvents = new();
        public IReadOnlyCollection<BaseEvent> DomainEvents => _domainEvents.AsReadOnly();
    
        public void AddDomainEvent(BaseEvent domainEvent)
        {
            _domainEvents.Add(domainEvent);
        }
    
        public void RemoveDomainEvent(BaseEvent domainEvent)
        {
            _domainEvents.Remove(domainEvent);
        }
    
        public void ClearDomainEvents()
        {
            _domainEvents.Clear();
        }
    
    }