Gil*_*rdo 2 .net c# asp.net composition simple-injector
我正在从继承转向合成,如您从此处看到的/sf/ask/2075720741/
现在,我已经完成了所有工作,但是简单的注入器希望我手动注册传入的每种类型的每个接口。这是简化的代码。
我有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();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我有一个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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我可以使用服务,并传递每个接口。所以我有一个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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在在我的配置文件中,我可以运行该文件,但是如果我有另一项服务,并且我有大约20个,我不想为每个服务都键入此文件。
container.Register<IEntityBaseService<Content>, EntityBaseService<Content>>();
container.Register<IValidationService<Content>, ValidationService<Content>>();
container.Register<IValidator<Content>, ContentValidator>();
container.Register<IContentService, ContentService>();
Run Code Online (Sandbox Code Playgroud)
所以我在网上看了一下,我认为我可以使用RegisterManyForOpenGeneric方法而不是注册IEntityBaseService和IValidatioNService,但我无法正常工作。我写了
container.RegisterManyForOpenGeneric(typeof(IEntityBaseService<>), typeof(IEntityBaseService<>).Assembly);
container.RegisterManyForOpenGeneric(typeof(IValidationService<>), typeof(IValidationService<>).Assembly);
Run Code Online (Sandbox Code Playgroud)
我得到一个错误的说法
ContentService类型的构造函数包含名称为“ service”且未注册的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;
}
}
Run Code Online (Sandbox Code Playgroud)
任何对简单注射器和代码的帮助都值得赞赏
您使用了错误的注册方法。
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);
Run Code Online (Sandbox Code Playgroud)
默认情况下,RegisterManyForOpenGeneric在提供的程序集中搜索实现[specified opengeneric]接口的所有类型,并通过其特定的(封闭的通用)接口注册每种类型。[强调我的]
注意具体类型本身不是通用的(即CustomerValidator实现封闭的通用接口IValidate<Customer>)。这对您而言效果很好,ContentValidator但对实现诸如EntityBaseService<Content>and和.NET这样的开放式通用接口的开放式通用类却不利ValidationService<Content>。
您正在寻找:-
container.RegisterOpenGeneric(
typeof(IEntityBaseService<>),
typeof(EntityBaseService<>));
Run Code Online (Sandbox Code Playgroud)