我正在从继承转向复合,正如你在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;
}
}
对简单注入器和一般代码
的任何帮助都非常赞赏答案 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