向Scrutor注册开放式通用装饰器

问题描述

我有一个标准的.Net核心Api,并且希望使用Open Generic IReposistory,并使用DomainEventPublisher对其进行修饰,以便在持久化后将事件推送到servicsBus。 但是,我很早以前就使用过Simple Injector,我对此非常感兴趣。但是现在,当使用MediatR Im时,我试图通过仅使用.net Core DI和scrutor软件包进行装饰来简化DI。

问题是我得到的错误: “提供的泛型参数的数量不等于泛型类型定义的复杂性。”尝试在“启动”中注册装饰器时从scrutor中访问(以下第二行)。

services.AddSingleton(typeof(IRepository<>),typeof(Repository<>));
services.Decorate(typeof(IRepository<>),typeof(DomainEventPublisher<>));

我已经关闭了这些通用的类/接口,然后它起作用了。但是我对此不好。我会以正确的方式像以前在Simpleinjector中所做的那样,并注册开放的通用装饰器。

任何建议可能是什么问题?

 public class Repository<TEntity> : IRepository<TEntity>
{
    private readonly CosmosClient _client;
    private readonly IDataContext<TEntity> _context;
    private readonly Container _container;

    public Repository(CosmosClient client,IDataContext<TEntity> context)
    {
        _client = client;
        _context = context ?? throw new ArgumentNullException(nameof(context));
        _container = _client.GetContainer(_context.GetDatabase(),_context.GetContainer());
    }


    public virtual async Task Add(TEntity entity)
    {
        try
        {
            var response = await _container.CreateItemAsync(entity,new PartitionKey(_context.GetPartitionKey(entity)));
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
      
    }

    public virtual async Task<TEntity> Get(string id)
    {
        var response = await _container.ReadItemAsync<TEntity>(id,new PartitionKey(_context.GetPartitionKey(id)));

        return response.Resource;
    }

    public virtual async Task<TEntity> Update(TEntity entity)
    {
        var response = await _container.UpsertItemAsync(entity,new PartitionKey(_context.GetPartitionKey(entity)));
        
        return response.Resource;
    }

    public async Task Remove(string id)
    {
        var response = await _container.DeleteItemAsync<TEntity>(id,new PartitionKey(_context.GetPartitionKey(id)));
    }

public class DomainEventPublisher<TEntity> : IRepository<TEntity>
{
    private readonly IRepository<TEntity> _decoratedRepository;
    private readonly ITopicAdapter _bus;
    private readonly IMapper _mapper;

    private List<IDomainEvent> _eventsToProcess = new List<IDomainEvent>();

    public DomainEventPublisher(IRepository<TEntity> decoratedRepository,ITopicAdapter bus,IMapper mapper)
    {
        _decoratedRepository = decoratedRepository ?? throw new ArgumentNullException(nameof(decoratedRepository));
        _bus = bus ?? throw new ArgumentNullException(nameof(bus));
        _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
    }
    public async Task Add(TEntity entity)
    {
        // Get all domain events raised by source entity
        var events = CollectEvents(entity);
        await _decoratedRepository.Add(entity);
        await HandleEvents(events);
    }

    public async Task<TEntity> Get(string id)
    {
        return await _decoratedRepository.Get(id);
    }

    public async Task<TEntity> Update(TEntity entity)
    {
        // Get all domain events raised by source entity
        var events = CollectEvents(entity);
        var result = await _decoratedRepository.Update(entity);
        await HandleEvents(events);

        return result;
    }

    public async Task Remove(string id)
    {
        await _decoratedRepository.Remove(id);
    }

    private List<IDomainEvent> CollectEvents(TEntity entity)
    {
        if (entity is IEntity entityWithEvents)
            return entityWithEvents.Events;

        return new List<IDomainEvent>();
    }

    private async Task HandleEvents(List<IDomainEvent> events)
    {
        // if we ended up on this line we kNow that repository persisted changes and Now send events to bus
        foreach (var domainEvent in events)
        {
            await _bus.Send(_mapper.MapTo(domainEvent));
        }
    }
}

解决方法

不可能将装饰器应用于Scrutor的开放式注册。 here在Scrutor论坛上进行了讨论。这是由于基础Microsoft DI容器的限制。这是Scrutor不能绕过的限制。

相反,请切换到确实支持此功能的成熟的DI容器之一。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...