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

时间:2015-04-16 14:52:09

标签: c# asp.net .net composition simple-injector

我正在从继承转向复合,正如你在https://stackoverflow.com/questions/29653153/composition-migrating-from-inheritance

所看到的那样

现在我已经完成了所有工作,但是简单的注入器希望我手动注册每个传入的类型的接口。这是条带化代码。

我有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);

我得到一个错误说

  

ContentService类型的构造函数包含type的参数   名称为&#39; service&#39;的IEntityBaseService那不是   注册。请确保注册IEntityBaseService   容器,或更改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;
    }

}

对简单注入器和一般代码

的任何帮助都非常赞赏

2 个答案:

答案 0 :(得分:4)

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

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);
  

默认情况下,RegisterManyForOpenGeneric在提供的程序集中搜索实现[指定的开放式通用]接口的所有类型,并通过 特定(封闭通用) 接口注册每种类型。 [强调我的]

请注意具体类型本身不是通用的(即CustomerValidator实现封闭的通用接口IValidate<Customer>)。这适用于ContentValidator,但对于实现开放式通用接口(例如EntityBaseService<Content>ValidationService<Content>)的开放式泛型类没有任何帮助。

您正在寻找: -

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

答案 1 :(得分:0)

RegisterManyForOpenGeneric现已被标记为过时。

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

现在就走了。

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