Search code examples
c#asp.net.netdependency-injectionmediatr

MediatR closed generic Handler is not called


I am using Notifications from MediatR for Cache Invalidation, for example Created, Updated and Deleted events for each entity in my application.

I am using some logic to add the handlers to my service collection, but the simplified and also not working version looks like this:

collection.AddTransient(
    typeof(IEventHandler<UpdatedEvent<RefreshToken, RefreshTokenId>>),
    typeof(UpdatedEventHandler<IRefreshTokenRepository, RefreshToken, RefreshTokenId, IRefreshTokenDto, UpdatedEvent<RefreshToken, RefreshTokenId>>));

And an example of how i would publish the notification looks like this:

await _mediator.Publish(new UpdatedEvent<RefreshToken, RefreshTokenId>(new RefreshToken(new UserId())), cancellationToken);

The implementation of the UpdatedEventHandler looks like this:

public class UpdatedEventHandler<TIRepository, TEntity, TId, TIDto, TUpdated> :     IEventHandler<TUpdated> 
    where TUpdated : UpdatedEvent<TEntity, TId>
    where TIRepository : IRepository<TEntity, TId, TIDto>
    where TEntity : Entity<TId>
    where TId : IdObject<TId>
    where TIDto : IDto<TId>
{
    private readonly TIRepository _repository;

    public UpdatedEventHandler(TIRepository repository)
    {
        _repository = repository;
    }

    public Task Handle(TUpdated updatedEvent, CancellationToken cancellationToken)
    {
        var _cacheKeys = GetBaseCacheKeysAsync(updatedEvent);

        return _repository.ClearCacheAsync(_cacheKeys);
    }

    private async IAsyncEnumerable<string> GetBaseCacheKeysAsync(TUpdated updatedEvent)
    {
        yield return await repository.EntityValueCacheKeyAsync(nameof(_repository.GetByIdAsync),
            updatedEvent.Updated.Id.Value.ToString());
        yield return await repository.EntityCacheKeyAsync(nameof(_repository.GetListAsync));
        
        await foreach (var cacheKey in GetCacheKeysAsync(updatedEvent))
        {
            yield return cacheKey;
        }
    }

    protected virtual IAsyncEnumerable<string> GetCacheKeysAsync(TUpdated updatedEvent)
    {
        throw new NotImplementedException("Override this method to add additional cache keys.");
    }
}

I have tried different things, but no matter what i do, the event handler does not get called.

I did try implementing explicit classes which inherit from the updatedEventHandler and refering the generic parameters and then it worked, but thats not really what i try to achieve. Whats also weird about this is, that the registering of the event handler stayed the same, but with the inheriting class, the event handler method was called.


Solution

  • I was using a custom Interface IEventHandler which was inheriting from INotificationHandler. I added my event handlers as IEventHandlers to the serviceCollection, when MediatR "searched" for INotificationHandlers for my notification to publish, nothing was found because of that.