Đây là Giải pháp và dự án của tôi:
- BookStore (giải pháp)
- BookStore.Coupler (dự án)
- Bootstrapper.cs
- BookStore.Domain (dự án)
- Tạo BookCommandValidator.cs
- CompositeValidator.cs
- IValidate.cs
- IValidator.cs
- ICommandHandler.cs
- BookStore.Infr Hạ tầng (dự án)
- Tạo BookCommandHandler.cs
- Xác nhậnCommandHandlerDecorator.cs
- BookStore.Web (dự án)
- Toàn cầu
- BookStore.BatchProcesses (dự án)
- Chương trình.cs
- BookStore.Coupler (dự án)
Bootstrapper.cs :
public static class Bootstrapper.cs
{
// I'm using SimpleInjector as my DI Container
public static void Initialize(Container container)
{
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>), typeof(CreateBookCommandHandler).Assembly);
container.RegisterDecorator(typeof(ICommandHandler<>), typeof(ValidationCommandHandlerDecorator<>));
container.RegisterManyForOpenGeneric(typeof(IValidate<>),
AccessibilityOption.PublicTypesOnly,
(serviceType, implTypes) => container.RegisterAll(serviceType, implTypes),
typeof(IValidate<>).Assembly);
container.RegisterSingleOpenGeneric(typeof(IValidator<>), typeof(CompositeValidator<>));
}
}
Tạo BookCommandValidator.cs
public class CreateBookCommandValidator : IValidate<CreateBookCommand>
{
public IEnumerable<IValidationResult> Validate(CreateBookCommand book)
{
if (book.Author == "Evan")
{
yield return new ValidationResult<CreateBookCommand>("Evan cannot be the Author!", p => p.Author);
}
if (book.Price < 0)
{
yield return new ValidationResult<CreateBookCommand>("The price can not be less than zero", p => p.Price);
}
}
}
CompositeValidator.cs
public class CompositeValidator<T> : IValidator<T>
{
private readonly IEnumerable<IValidate<T>> validators;
public CompositeValidator(IEnumerable<IValidate<T>> validators)
{
this.validators = validators;
}
public IEnumerable<IValidationResult> Validate(T instance)
{
var allResults = new List<IValidationResult>();
foreach (var validator in this.validators)
{
var results = validator.Validate(instance);
allResults.AddRange(results);
}
return allResults;
}
}
IValidate.cs
public interface IValidate<T>
{
IEnumerable<IValidationResult> Validate(T instance);
}
IValidator.cs
public interface IValidator<T>
{
IEnumerable<IValidationResult> Validate(T instance);
}
ICommandHandler.cs
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
Tạo BookCommandHandler.cs
public class CreateBookCommandHandler : ICommandHandler<CreateBookCommand>
{
private readonly IBookStore _bookStore;
public CreateBookCommandHandler(IBookStore bookStore)
{
_bookStore = bookStore;
}
public void Handle(CreateBookCommand command)
{
var book = new Book { Author = command.Author, Name = command.Name, Price = command.Price };
_bookStore.SaveBook(book);
}
}
Xác nhậnCommandHandlerDecorator.cs
public class ValidationCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> decorated;
private readonly IValidator<TCommand> validator;
public ValidationCommandHandlerDecorator(ICommandHandler<TCommand> decorated, IValidator<TCommand> validator)
{
this.decorated = decorated;
this.validator = validator;
}
public void Handle(TCommand command)
{
var results = validator.Validate(command);
if (!results.IsValid())
{
throw new ValidationException(results);
}
decorated.Handle(command);
}
}
Toàn cầu
// inside App_Start()
var container = new Container();
Bootstrapper.Initialize(container);
// more MVC specific bootstrapping to the container. Like wiring up controllers, filters, etc..
Chương trình.cs
// Pretty much the same as the Global.asax
Xin lỗi vì thiết lập lâu cho vấn đề, tôi không có cách nào tốt hơn để giải thích vấn đề này ngoài việc nêu chi tiết vấn đề thực sự của tôi.
Tôi không muốn tạo CreatBookCommandValidator của mình public
. Tôi thà như vậy internal
nhưng nếu tôi làm được internal
thì tôi sẽ không thể đăng ký với DI Container của mình. Lý do tôi muốn nó là nội bộ là vì dự án duy nhất nên có khái niệm về các triển khai IValidate <> của tôi nằm trong dự án BookStore.Domain. Bất kỳ dự án nào khác chỉ cần tiêu thụ IValidator <> và CompositeValidator phải được giải quyết sẽ đáp ứng tất cả các xác nhận.
Làm cách nào tôi có thể sử dụng Dependency Injection mà không phá vỡ đóng gói? Hay tôi đi sai về điều này?