Hier ist meine Lösung und Projekte:
- BookStore (Lösung)
- BookStore.Coupler (Projekt)
- Bootstrapper.cs
- BookStore.Domain (Projekt)
- CreateBookCommandValidator.cs
- CompositeValidator.cs
- IValidate.cs
- IValidator.cs
- ICommandHandler.cs
- BookStore.Infrastructure (Projekt)
- CreateBookCommandHandler.cs
- ValidationCommandHandlerDecorator.cs
- BookStore.Web (Projekt)
- Global.asax
- BookStore.BatchProcesses (Projekt)
- Program.cs
- BookStore.Coupler (Projekt)
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<>));
}
}
CreateBookCommandValidator.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);
}
CreateBookCommandHandler.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);
}
}
ValidationCommandHandlerDecorator.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);
}
}
Global.asax
// inside App_Start()
var container = new Container();
Bootstrapper.Initialize(container);
// more MVC specific bootstrapping to the container. Like wiring up controllers, filters, etc..
Program.cs
// Pretty much the same as the Global.asax
Entschuldigung für die lange Einrichtung des Problems, ich habe keine bessere Möglichkeit, dies zu erklären, als mein eigentliches Problem zu beschreiben.
Ich möchte meinen CreateBookCommandValidator nicht erstellen public
. Es wäre mir lieber, internal
aber wenn ich es schaffe, kann internal
ich es nicht bei meinem DI Container registrieren. Der Grund, warum ich möchte, dass es intern ist, ist, dass sich das einzige Projekt, das von meinen IValidate <> -Implementierungen Kenntnis haben sollte, im BookStore.Domain-Projekt befindet. Jedes andere Projekt muss nur IValidator <> verbrauchen und der CompositeValidator sollte aufgelöst werden, der alle Validierungen erfüllt.
Wie kann ich Dependency Injection verwenden, ohne die Kapselung zu beschädigen? Oder mache ich das alles falsch?