具有通用接口和组合的简单注入器 - 不注册接口

Simple Injector with Generic interfaces and composition - Not registering interfaces

我正在从继承转向组合,正如你从这里看到的那样

现在我已经完成了所有工作,但是简单的注入器要我手动注册每个接口与传入的每种类型。这是精简代码。

我有 IBaseEntityService,它实现了 BaseEntityService,就像这样

public interface IEntityBaseService<T> where T : class, IEntityBase
{
    IDataContext Context { get; }

    Task<ICollection<T>> GetAllAsync();

    Task<T> GetAsync(long id);
}

public class EntityBaseService<T> : IEntityBaseService<T>
    where T : class, IEntityBase
{
    protected IDataContext _context;

    public IDataContext Context
    {
        get
        {
            return _context;
        }
    }

    public EntityBaseService(IDataContext context)
    {
        _context = context;
    }

    public async Task<ICollection<T>> GetAllAsync()
    {
        return await _context.Set<T>().ToListAsync();
    }

    public Task<T> GetAsync(long id)
    {
        return _context.Set<T>().Where(e => e.Id == id).FirstOrDefaultAsync();
    }
}

现在我有一个 IValidationService 和 ValidationService 实现它,就像这样

public interface IValidationService<T> 
    where T : class, IEntityBase
{
    Task<ValidationResult> ValidateAsync(T entity);

    Task<int> AddAsync(T entity);

    Task<int> UpdateAsync(T entity);
}

public class ValidationService<T> : IValidationService<T>
    where T : class, IEntityBase
{
    private IEntityBaseService<T> _service;
    private IValidator<T> _validator = null;

    public IDataContext Context
    {
        get
        {
            return _service.Context;
        }
    }

    public ValidationService(IEntityBaseService<T> service, IValidator<T> validator)
    {
        _service = service;
        _validator = validator;
    }

    public Task<ValidationResult> ValidateAsync(T entity)
    {
        if (_validator == null) throw new MissingFieldException("Validator does not exist for class " + entity.GetType().ToString() + ". override method if no validation needed");
        return _validator.ValidateAsync(entity);
    }

    public async Task<int> AddAsync(T entity)
    {
        var results = await ValidateAsync(entity);

        if (!results.IsValid)
        {
            throw new ValidationException(results.Errors);
        }

        return await _service.AddAsync(entity);
    }

    public async Task<int> UpdateAsync(T entity)
    {
        var results = await ValidateAsync(entity);

        if (!results.IsValid)
        {
            throw new ValidationException(results.Errors);
        }

        return await _service.UpdateAsync(entity);
    }
}

现在可以使用服务了,可以传入各个接口了。所以我有一个 IContentService 和 ContentService 来实现它。此服务同时使用 IEntityBaseService 和 IValidationService

public interface IContentService
{
    Task<Content> GetAsync(long id);

    Task<int> AddAsync(Content entity);

    Task<int> UpdateAsync(Content entity);
}

public class ContentService : IContentService
{
    private IEntityBaseService<Content> _service;
    private IValidationService<Content> _validation;

    public ContentService(IEntityBaseService<Content> service, IValidationService<Content> validation)
    {
        _service = service;
        _validation = validation;
    }

    public async Task<Content> GetAsync(long id)
    {
        var content = await _service.Context.Contents
            .Where(e => e.Id == id)
            .WhereNotDeleted()
            .FirstOrDefaultAsync();

        if (content != null)
        {
            content.Attachments = await _service.Context.Attachments
                .Where(e => e.ContentId == id)
                .WhereNotDeleted()
                .ToListAsync();
        }

        return content;
    }

    public Task<int> AddAsync(Content entity)
    {
        return _validation.AddAsync(entity);
    }

    public Task<int> UpdateAsync(Content entity)
    {
        return _validation.UpdateAsync(entity);
    }
}

现在在我的配置文件中,我有这个,它可以工作,但是如果我有另一个服务,并且我有大约 20 个服务,我不想为每个服务都输入这个。

container.Register<IEntityBaseService<Content>, EntityBaseService<Content>>();
container.Register<IValidationService<Content>, ValidationService<Content>>();
container.Register<IValidator<Content>, ContentValidator>();

container.Register<IContentService, ContentService>();

所以我在网上看了看,我想我可以使用 RegisterManyForOpenGeneric 方法而不是注册 IEntityBaseService 和 IValidatioNService,但我无法让它发挥作用。我写了

container.RegisterManyForOpenGeneric(typeof(IEntityBaseService<>), typeof(IEntityBaseService<>).Assembly);
container.RegisterManyForOpenGeneric(typeof(IValidationService<>), typeof(IValidationService<>).Assembly);

我收到一条错误消息

The constructor of type ContentService contains the parameter of type IEntityBaseService with name 'service' that is not registered. Please ensure IEntityBaseService is registered in the container, or change the constructor of ContentService.

可能是我的实体设置不正确,所以就装箱吧,这里是这个例子的基本实体

public interface IEntityBase
{
    long Id { get; set; }
}

public abstract class EntityBase : IEntityBase
{
    public long Id { get; set; }
}

public class Content : EntityBase, IAudit
{
    public short Position { get; set; }

    public Content() 
    {
        Position = 1;
    }

}

对简单注入器和一般代码的任何帮助都非常感谢

您使用了错误的注册方法。

RegisterManyForOpenGeneric 存在以支持以下场景:-

container.Register<IValidate<Customer>, CustomerValidator>();
container.Register<IValidate<Employee>, EmployeeValidator>();
container.Register<IValidate<Order>, OrderValidator>();
container.Register<IValidate<Product>, ProductValidator>();

// can replace the above with the following:-
container.RegisterManyForOpenGeneric(
  typeof(IValidate<>),
  typeof(IValidate<>).Assembly);

By default RegisterManyForOpenGeneric searches the supplied assembly for all types that implement the [specified open generic] interface and registers each type by their specific (closed generic) interface. [Emphasis mine]

请注意具体类型本身不是通用的(即 CustomerValidator 实现了封闭的通用接口 IValidate<Customer>)。这对你的 ContentValidator 很好,但对开放通用 类 实现开放通用接口如你的 EntityBaseService<Content>ValidationService<Content>.

没有好处

您正在寻找:-

container.RegisterOpenGeneric(
  typeof(IEntityBaseService<>),
  typeof(EntityBaseService<>));

RegisterManyForOpenGeneric 现在已被标记为过时。

container.Register(typeof(IValidator<>), new[] { typeof(IValidator<>).Assembly });

是现在要走的路。

http://simpleinjector.readthedocs.org/en/latest/advanced.html