-
Notifications
You must be signed in to change notification settings - Fork 15
Home
Nelson Júnior edited this page Jun 12, 2016
·
4 revisions
Welcome to the enjoy.cqrs wiki!
Development version (MyGet):
Install-Package EnjoyCQRS -Source https://www.myget.org/F/enjoy/api/v3/index.json
Released version (NuGet):
Install-Package EnjoyCQRS
You will need to implement these abstractions:
- CommandDispatcher
- IEventRouter
- IEventStore
- ILoggerFactory (you can use the dummy implementation called: NoopLoggerFactory)
You'll need to configure dependencies:
Autofac example:
var builder = new ContainerBuilder();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
builder.RegisterType<Session>().As<ISession>().InstancePerLifetimeScope();
builder.RegisterType<Repository>().As<IRepository>();
builder.Register(c => new IntervalSnapshotStrategy()).As<ISnapshotStrategy>();
builder.RegisterType<NoopLoggerFactory>().As<ILoggerFactory>().InstancePerLifetimeScope();
builder.RegisterType<EventPublisher>().As<IEventPublisher>().InstancePerLifetimeScope();
Register your command handlers:
var genericCommandHandler = typeof(ICommandHandler<>);
builder.RegisterAssemblyTypes(typeof(FooCommandHandler).Assembly)
.AsClosedTypesOf(genericCommandHandler)
.AsImplementedInterfaces();
And your event handlers:
var genericEventHandler = typeof(IEventHandler<>);
builder.RegisterAssemblyTypes(typeof(FooEventHandler).Assembly)
.AsClosedTypesOf(genericEventHandler)
.AsImplementedInterfaces();
public class AutofacEventRouter : IEventRouter
{
private readonly ILifetimeScope _scope;
public AutofacEventRouter(ILifetimeScope scope)
{
_scope = scope;
}
public async Task RouteAsync<TEvent>(TEvent @event)
where TEvent : IDomainEvent
{
var handlers = _scope.ResolveOptional<IEnumerable<IEventHandler<TEvent>>>();
foreach (var handler in handlers)
{
await handler.ExecuteAsync(@event).ConfigureAwait(false);
}
}
}
public class AutofacCommandDispatcher : CommandDispatcher
{
private readonly ILifetimeScope _scope;
public AutofacCommandDispatcher(ILifetimeScope scope)
{
_scope = scope;
}
protected override async Task RouteAsync<TCommand>(TCommand command)
{
var handler = _scope.Resolve<ICommandHandler<TCommand>>();
await handler.ExecuteAsync(command);
}
}
public class Person : Aggregate
{
public string Name { get; private set; }
public Person() { }
public Person(Guid id, string name) : this()
{
Emit(new PersonCreated(id, name));
}
protected override void RegisterEvents()
{
SubscribeTo<PersonCreated>(evt =>
{
Id = evt.AggregateId;
Name = evt.Name;
});
SubscribeTo<NameChanged>(evt =>
{
Name = evt.Name;
});
}
public void ChangeName(string name)
{
Emit(new NameChanged(Id, name));
}
}
public class PersonCreated : DomainEvent
{
public string Name { get; }
public PersonCreated(Guid aggregateId, string name) : base(aggregateId)
{
Name = name;
}
}
public class CreatePerson : Command
{
public string Name { get; }
public CreatePerson(Guid id, string name) : base(id)
{
Name = name;
}
}
public class CreatePersonHandler : ICommandHandler<CreatePerson>
{
private readonly IRepository _repository;
public CreatePersonHandler(IRepository repository)
{
_repository = repository;
}
public Task ExecuteAsync(CreatePerson command)
{
var person = new Person(command.AggregateId, command.Name);
_repository.AddAsync(person);
return Task.CompletedTask;
}
}
public class PersonCreatedEventHandler : IEventHandler<PersonCreated>
{
public Task ExecuteAsync(PersonCreated @event)
{
Console.WriteLine(@event);
return Task.CompletedTask;
}
}
The full Autofac example looks like:
var builder = new ContainerBuilder();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
builder.RegisterType<Session>().As<ISession>().InstancePerLifetimeScope();
builder.RegisterType<Repository>().As<IRepository>();
builder.Register(c => new IntervalSnapshotStrategy()).As<ISnapshotStrategy>();
builder.RegisterType<NoopLoggerFactory>().As<ILoggerFactory>().InstancePerLifetimeScope();
builder.RegisterType<EventPublisher>().As<IEventPublisher>().InstancePerLifetimeScope();
builder.RegisterType<AutofacEventRouter>().As<IEventRouter>();
builder.RegisterType<AutofacCommandDispatcher>().As<ICommandDispatcher>();
var genericCommandHandler = typeof(ICommandHandler<>);
builder.RegisterAssemblyTypes(typeof(FooCommandHandler).Assembly)
.AsClosedTypesOf(genericCommandHandler)
.AsImplementedInterfaces();
var genericEventHandler = typeof(IEventHandler<>);
builder.RegisterAssemblyTypes(typeof(FooEventHandler).Assembly)
.AsClosedTypesOf(genericEventHandler)
.AsImplementedInterfaces();
var container = builder.Build();