Autofac: Custom delegate for single instance object exposed via interface - c#

Consider the below code:
public interface IProduct { };
public class ConcreteProduct : IProduct
{
public ConcreteProduct(int id, DateTime manufacturedDate, DateTime expiryDate)
{
}
}
public delegate IProduct ProductFactory(int id, DateTime manufacturedDate, DateTime expiryDate);
I need to maintain a single instance for the IProduct, which is to be created by someone by calling the ProductFactory delegate, which will return a ConcreteProduct.
Please suggest how to achieve this with Autofac.

Please try below:
public delegate IProduct ProductFactory(int id, DateTime manufacturedDate, DateTime expiryDate);
public interface IProduct { };
public class ConcreteProduct : IProduct
{
public int ProductId { get; set; }
public DateTime ManufactureDt { get; set; }
public DateTime ExpiryDt { get; set; }
public ConcreteProduct(int id, DateTime manufacturedDate, DateTime expiryDate)
{
ProductId = id;
ManufactureDt = manufacturedDate;
ExpiryDt = expiryDate;
}
}
//Class where Factory is injected
public class ProductOrder
{
private readonly ProductFactory _prodFactory;
public ProductOrder(ProductFactory prodFactory)
{
_prodFactory = prodFactory;
}
public IProduct GenerateOrder()
{
return _prodFactory.Invoke(10, DateTime.Now, DateTime.Now.AddDays(4));
}
}
Autofac registrations:
static IContainer container;
private static void InitializeAutoFac()
{
var builder = new ContainerBuilder();
builder.Register<ProductFactory>(context =>
{
return (int id, DateTime dt, DateTime dt2) =>
{
IProduct prod = new ConcreteProduct(id, dt, dt2);
return prod;
};
}).SingleInstance();
builder.RegisterType<ProductOrder>().AsSelf();
container = builder.Build();
}
Usage:
static void Main()
{
InitializeAutoFac();
ProductOrder pOrder = container.Resolve<ProductOrder>();
IProduct prod = pOrder.GenerateOrder();
}
Hope it helps.

Related

Create factory with using microsoft DI

I have hierarchy classes and generic classes of http reauest, response:
public abstract class Publication
{
public string Name { get; set; }
public string Producer { get; set; }
}
public class Book : Publication
{
public string Topic { get; set; }
public string Autor { get; set; }
}
public class CopyBook : Publication
{
public string Topic { get; set; }
public int CountPages { get; set; }
}
public class NoteBook : Publication
{
public int Cost { get; set; }
}
public class Request<T> where T : Publication
{
public Guid RequestId { get; }
public T Publication { get; }
public Request(T publication)
{
RequestId = Guid.NewGuid();
Publication = publication;
}
}
public class Response<T> where T : Publication
{
private Guid ResponseId { get; set; }
public T Publication { get; set; }
}
I use Http API client with Refit library. For it I create interface:
public interface IPublicationApiClinet<T> where T : Publication
{
bool Send(Request<T> publication);
Response<T> UpdatingRecv(Request<T> publication);
}
The refit library create implementation for the interface automatically. The refit library not injecting client with base class IFormApiClinet only child classes - for example IFormApiClinet.
I want to create factory to creation clients depend on type publication. I created her:
public interface IClientFactory
{
IPublicationApiClient<Publication> Create(Publication publication);
}
public class ClientFactory : IClientFactory
{
private readonly IServiceProvider _serviceProvider;
public ClientFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IPublicationApiClient<Publication> Create(Publication publication)
{
switch (publication)
{
case Book _:
return _serviceProvider.GetService<IPublicationApiClient<Book>>();
case NoteBook _:
return _serviceProvider.GetService<IPublicationApiClient<NoteBook>>();
case CopyBook _:
return _serviceProvider.GetService<IPublicationApiClient<CopyBook>>();
default:
throw new NotSupportedException();
}
}
}
The factory does not compile because IPublicationApiClient with child class don't cast to base class for returning. For example IPublicationApiClient<Book> to IPublicationApiClient<Publication>. How fix it?
I will use the factory in service, which getting publications of different types (Book, CopyBook, NoteBook) from DB.
public interface IPublicationSerice
{
void Proccess(string name);
}
public class PublicationSerice : IPublicationSerice
{
private readonly IClientFactory _clientFactory;
public PublicationSerice(IClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public void Proccess(string name)
{
Publication book = new Book();
//It is analog:
//var specification = new PublicationByNameSpecification<Publication>(name);
//var publication = await _publicationRepository.GetAsync(specification);
var bookClient = _clientFactory.Create(book);
bookClient.Send(new Request<Publication>(book));
}
}
You can do this by making the ClientFactory method generic as well:
public interface IClientFactory
{
IPublicationApiClient<T> Create<T>(T publication) where T : Publication;
}
public class ClientFactory : IClientFactory
{
private readonly IServiceProvider _serviceProvider;
public ClientFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IPublicationApiClient<T> Create<T>(T publication) where T : Publication
{
return _serviceProvider.GetService<IPublicationApiClient<T>>()
?? throw new NotSupportedException();
}
}
Here's a simple example of that working:
public class PublicationApiClient<T> : IPublicationApiClient<T> where T : Publication
{
public bool Send(Request<T> publication)
{
Console.WriteLine($"Hello from {typeof(T).Name} client!");
return true;
}
public Response<T> UpdatingRecv(Request<T> publication)
{
throw new NotImplementedException();
}
}
static void Main(string[] args)
{
ServiceProvider provider = new ServiceCollection()
.AddSingleton<IClientFactory, ClientFactory>()
.AddSingleton(typeof(IPublicationApiClient<>), typeof(PublicationApiClient<>))
.BuildServiceProvider();
IClientFactory factory = provider.GetService<IClientFactory>();
Book book = new Book();
IPublicationApiClient<Book> bookClient = factory.Create(book);
bookClient.Send(new Request<Book>(book));
NoteBook notebook = new NoteBook();
IPublicationApiClient<NoteBook> notebookClient = factory.Create(notebook);
notebookClient.Send(new Request<NoteBook>(notebook));
Console.ReadLine();
}
Which produces the following output:

Best Implementation to avoid if/else

I am doing a program for vacation in a company and the time that is allowed to be in a specific holiday.
I used an Abstract class with an abstract method :
public abstract class Abstract : TimeLength
{
public AbstractTest(string employeeCode, string employee, string typeOfHoliday, DateTime startDate, DateTime endDate) : base(startDate, endDate, "")
{
TypeOfHoliday = typeOfHoliday;
Employee = employee;
EmployeeCode = employeeCode;
}
public string EmployeeCode { get; set; }
public string Employee { get; set; }
public string TypeOfHoliday { get; set; }
public abstract bool HolidayValidation(string typeOfHoliday);
}
And I used multiple class that inherent from this abstract class like this two :
class MarriageVacation : Abstract
{
public MarriageVacation(string employeeCode, string employee, string typeOfHoliday, DateTime startDate, DateTime endDate) : base(employeeCode, employee, typeOfHoliday, startDate, endDate)
{
}
public override bool HolidayValidation(string typeOfHoliday)
{
if (Days() > (int)Holiday.MarriageVacation)
{
MessageBox.Show("Marriage Vacation Can only be 5 Days");
return false;
}
else
return true;
}
}
class Bereavement : Abstract
{
public Bereavement(string employeeCode, string employee, string typeOfHoliday, DateTime startDate, DateTime endDate) : base(employeeCode, employee, typeOfHoliday, startDate, endDate)
{
}
public override bool HolidayValidation(string typeOfHoliday)
{
if (Days() > (int)Holiday.Bereavement)
{
MessageBox.Show("Bereavement Can only be 5 Days");
return false;
}
else
return true;
}
}
I use Enum for holidays
and in the main I want to register this based on the users choice like this :
List<Abstract> holiday = new List<Abstract>();
if(CmbTypeHolidays.Text == Holiday.Bereavement.ToString())
{
var holid = new Bereavement(CmbEmpHolidays.Text.Split('-')[0], CmbEmpHolidays.Text.Split('-')[1], CmbTypeHolidays.Text, Convert.ToDateTime(StartDateHolidays.Value), Convert.ToDateTime(EndDateHolidays.Value));
if (holid.HolidayValidation(CmbTypeHolidays.Text))
{
holiday.Add(holid);
var bindingList = new BindingList<Abstract>(holiday);
dataGridHolidays.DataSource = bindingList;
controlPanelHolidays.Visible = false;
}
}
else if (CmbTypeHolidays.Text == Holiday.MarriageVacation.ToString())
{
var holid = new MarriageVacation(CmbEmpHolidays.Text.Split('-')[0], CmbEmpHolidays.Text.Split('-')[1], CmbTypeHolidays.Text, Convert.ToDateTime(StartDateHolidays.Value), Convert.ToDateTime(EndDateHolidays.Value));
if (holid.HolidayValidation(CmbTypeHolidays.Text))
{
holiday.Add(holid);
var bindingList = new BindingList<Abstract>(holiday);
dataGridHolidays.DataSource = bindingList;
controlPanelHolidays.Visible = false;
}
}
I wanted to know a better way to implement this solution or just to change the code that inserts data to the abstract List
You will need to set up a factory that maps holiday type name to the class implementing it:
private class HolidayConstructorArgs {
public string EmployeeCode {get;set;}
public string Employee {get;set;}
public string TypeOfHoliday {get;set;}
public DateTime From {get;set;}
public DateTime To {get;set;}
}
private static readonly IDictionary<string,Func<HolidayConstructorArgs,AbstractHoliday>> HolidayByTypeCode =
new Dictionary<string,Func<HolidayConstructorArgs,AbstractHoliday>> {
[$"{Holiday.Bereavement}"] = a => new Bereavement(a.EmployeeCode, a.Employee, a.TypeOfHoliday, a.From, a.To)
, [$"{Holiday.MarriageVacation}"] = a => new MarriageVacation(a.EmployeeCode, a.Employee, a.TypeOfHoliday, a.From, a.To)
};
Now you can get the factory from the dictionary, and use it to instantiate the object:
if (HolidayByTypeCode.TryGetValue(CmbTypeHolidays.Text, out var factory)) {
// This is where the "magic" happens:
// Func<> will invoke the appropriate constructor without a conditional
var holid = factory(
new HolidayConstructorArgs {
EmployeeCode = CmbEmpHolidays.Text.Split('-')[0]
, Employee = CmbEmpHolidays.Text.Split('-')[1]
, TypeOfHoliday = CmbTypeHolidays.Text
, From = Convert.ToDateTime(StartDateHolidays.Value)
, To = Convert.ToDateTime(EndDateHolidays.Value)
}
);
// ... The rest of your code remains the same
}
I made this changes based on the answers on this questions this is the Main class (Abstract) :
public class AbstractTest : TimeLength
{
public AbstractTest(string employeeCode, string employee, Holiday typeOfHoliday, DateTime startDate, DateTime endDate) : base(startDate, endDate, "")
{
TypeOfHoliday = typeOfHoliday;
Employee = employee;
EmployeeCode = employeeCode;
}
public string EmployeeCode { get; set; }
public string Employee { get; set; }
public Holiday TypeOfHoliday { get; set; }
public bool HolidayValidation(Holiday typeOfHoliday)
{
return Days() > (int)typeOfHoliday;
}
}
And in the Main i changed into this :
Holiday MyStatus = (Holiday)Enum.Parse(typeof(Holiday), CmbTypeHolidays.Text, true);
var holid = new AbstractTest(CmbEmpHolidays.Text.Split('-')[0], CmbEmpHolidays.Text.Split('-')[1], MyStatus, Convert.ToDateTime(StartDateHolidays.Value), Convert.ToDateTime(EndDateHolidays.Value));
if (!holid.HolidayValidation(MyStatus))
{
holiday.Add(holid);
var bindingList = new BindingList<AbstractTest>(holiday);
dataGridHolidays.DataSource = bindingList;
controlPanelHolidays.Visible = false;
}
else
{
MessageBox.Show($"{holid.TypeOfHoliday} Cant be more than {(int)MyStatus} Days");
}
For the typeOfHoliday i used Holiday type so it is easier to work with and the choice that the user makes i convert it to Enum Holiday
You have the same(almost) implementation for HolidayValidation and you dont use typeOfHoliday.
From what you have posted you might as well add the Holiday enum as parameter and property to base class(Abstract) and not have any inheritance at all.
Implement the HolidayValidation in the base class and use the Holiday property to compare to Days

Maping generic interface to concreate class but using interface definition -> automapper

Hey I'm trying to map my generic class to concrete class but using it's interface.
My service returns me data which type is
IPaggedResults<Customer>
and I want to be able to map this to
IPaggedResults<CustomerDto>
It works if I invoke mapping with:
_mapper.Map<PaggedResults<CustomerDto>>
but I want use following syntax:
_mapper.Map<IPaggedResults<CustomerDto>>
public class PaggedResults<T> : IPaggedResults<T>
{
public IEnumerable<T> Results { get; protected set; }
public int TotalResults { get; protected set; }
public int TotalPages { get; protected set; }
public int ResultsPerPage { get; protected set; }
public PaggedResults(IEnumerable<T> results, int totalResults, int resultsPerPage)
{
Results = results;
TotalResults = totalResults;
TotalPages = totalResults / resultsPerPage;
ResultsPerPage = resultsPerPage;
}
}
public class CustomerDto
{
public int Id { get; set; }
public string Name { get; set; }
public string NIP { get; set; }
}
My mapper configuration:
public static IMapper Initialize()
=> new MapperConfiguration(cfg =>
{
cfg.CreateMap<CustomerCompany, CustomerDto>();
cfg.CreateMap(typeof(IPaggedResults<>), typeof(PaggedResults<>));
cfg.CreateMap(typeof(IPaggedResults<>), typeof(IPaggedResults<>)).As(typeof(PaggedResults<>));
}).CreateMapper();
Im'using Automapper by Jimmy Bogard.
I could achieve it through the following code:
Create an extension for IMapperConfigurationExpression
public static class IMapperConfigurationExpressionExtensions
{
public static void MapPaggedResults<TSource, TDestination>(this IMapperConfigurationExpression exp){
exp.CreateMap(typeof(PaggedResults<TSource>), typeof(IPaggedResults<TDestination>))
.ConstructUsing((source, ctx) => { return ctx.Mapper.Map<PaggedResults<TDestination>>(source) as IPaggedResults<TDestination>; });
}
}
Then use this configuration:
public static IMapper Initialize()
=> new MapperConfiguration(cfg =>
{
cfg.CreateMap(typeof(IPaggedResults<>), typeof(PaggedResults<>));
cfg.MapPaggedResults<CustomerCompany, CustomerDto>();
}).CreateMapper();
Then both results can be obtained:
var _mapper = Initialize();
IPaggedResults<CustomerCompany> source = new PaggedResults<CustomerCompany>(
new List<CustomerCompany>() { new CustomerCompany() {Id =42, Name = "SomeName", NIP = "someNIP" } }, 1, 1);
var resut = _mapper.Map<PaggedResults<CustomerDto>>(source);
var resut2 = _mapper.Map<IPaggedResults<CustomerDto>>(source);

is it a good practice to pass an EF DbContext as delegate in services to attach all changes on it

Having the following context:
public class DemoContext : DbContext
{
private readonly string _connectionStringName = "DemoContext";
public DemoContext() : base("name=DemoContext")
{
//_connectionStringName = "DemoContext";
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
//Database.SetInitializer(new MigrateDatabaseToLatestVersion<DemoContext, Migrations.Configuration>(_connectionStringName));
Database.SetInitializer(new NullDatabaseInitializer<DemoContext>());
}
public DbSet<Employee> Employees { get; set; }
public DbSet<Company> Companies { get; set; }
}
public class Employee
{
[Key]
public int EmployeeId { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class Company
{
[Key]
public int CompanyId { get; set; }
public string CompanyName { get; set; }
}
And this services:
public class EmployeeSvc
{
private readonly DemoContext _context;
public EmployeeSvc(Func<DemoContext> context)
{
_context = context();
}
public void Add(EmployeeAgg employee)
{
_context.Employees.Attach(new Employee()
{
Name = employee.Name,
DateOfBirth = employee.DateOfBirth
});
}
public void UpdateAll()
{
var employees = _context.Employees.ToList();
foreach (var employee in employees)
{
employee.Name = $"{Guid.NewGuid()}";
}
}
}
public class CompanySvc
{
private readonly DemoContext _context;
public CompanySvc(Func<DemoContext> context)
{
_context = context();
}
public void Add(CompanyAgg company)
{
_context.Companies.Attach(new Company()
{
CompanyName = company.CompanyName
});
}
public void UpdateAll()
{
var empresas = _context.Companies.ToList();
foreach (var empresa in empresas)
{
empresa.CompanyName = $"{Guid.NewGuid()}";
}
}
}
public class EmployeeAgg
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class CompanyAgg
{
public string CompanyName { get; set; }
}
Anf the following client code:
static void Main(string[] args)
{
var context = new DemoContext();
// ReSharper disable AccessToDisposedClosure
var employeeSvc = new EmployeeSvc(() => context);
var companySvc = new CompanySvc(() => context);
// ReSharper restore AccessToDisposedClosure
Console.WriteLine("Adding entities to context inside services");
employeeSvc.Add(new EmployeeAgg()
{
DateOfBirth = DateTime.Now.AddYears(-10),
Name = $"Employee name"
});
companySvc.Add(new CompanyAgg()
{
CompanyName = $"Company name"
});
employeeSvc.UpdateAll();
companySvc.UpdateAll();
context.SaveChanges();
context.Dispose();
Console.ReadLine();
}
Is it a good practice passing DbContext to application services as delegate in order to have a reference to a single instance and track all changes on it?
Maybe it's your example code, but there's no need here to use a delegate. You could as well just accept a DbContext and pass in the same instance:
public class EmployeeSvc
{
private readonly DemoContext _context;
public EmployeeSvc(DemoContext context)
{
_context = context();
}
// snip ...
}
public class CompanySvc
{
private readonly DemoContext _context;
public CompanySvc(DemoContext context)
{
_context = context();
}
// snip ...
}
var context = new DemoContext();
var employeeSvc = new EmployeeSvc(context);
var companySvc = new CompanySvc(context);
This would give you the exact same result, without needing to pass in a delegate and immediately invoking it.
I suppose however that maybe your actual code is a bit more complicated. If so, you should look into dependency injection and a DI-container.
A DI-container allows you to manage your dependencies and their lifecycles. A common lifecycle is the Singleton lifecycle, where the container will always construct your dependencies passing in the same instance.
if you need to injection your dbContext is better to use interface.
func<> is not suitable.
in Dependency injection interface is suitable.
(excusme for bad english)

How to use eventstore in cqrs pattern

I am working on a CQRS pattern. I have created one project related to this approach in which I can insert and retrieve data. I came to know that there are two different models Write Model(Commands) and Read Model(Query). I just want to know that my approach for write model is right or not. And how to use temporarily database for event sourcing when multiple users doing same operations.
Command.cs
public class Command : Message
{
}
public class Insert : Command
{
public readonly Guid Id;
public readonly string Name;
public Insert(Guid id, string name)
{
Id = id;
Name = name;
}
}
public class Update : Command
{
public readonly Guid Id;
public readonly string NewName;
public readonly int OriginalVersion;
public Update(Guid id, string newName)
{
Id = id;
NewName = newName;
}
}
public class Delete : Command
{
public Guid Id;
public readonly int OriginalVersion;
public Delete(Guid id)
{
Id = id;
}
}
Event.cs
public class Event:Message
{
public int Version;
}
public class Inserted : Event
{
public readonly Guid Id;
public readonly string Name;
public Inserted(Guid id, string name)
{
Id = id;
Name = name;
}
}
public class Updated : Event
{
public readonly Guid Id;
public readonly string NewName;
public readonly int OriginalVersion;
public Updated(Guid id, string newName)
{
Id = id;
NewName = newName;
}
}
public class Deleted : Event
{
public Guid Id;
public Deleted(Guid id)
{
Id = id;
}
}
EventStore.cs
public interface IEventStore
{
void SaveEvents(Guid aggregateId, IEnumerable<Event> events, int expectedVersion);
List<Event> GetEventsForAggregate(Guid aggregateId);
}
public class EventStore : IEventStore
{
private readonly IEventPublisher _publisher;
private struct EventDescriptor
{
public readonly Event EventData;
public readonly Guid Id;
public readonly int Version;
public EventDescriptor(Guid id, Event eventData, int version)
{
EventData = eventData;
Version = version;
Id = id;
}
}
public EventStore(IEventPublisher publisher)
{
_publisher = publisher;
}
private readonly Dictionary<Guid, List<EventDescriptor>> _current = new Dictionary<Guid, List<EventDescriptor>>();
public void SaveEvents(Guid aggregateId, IEnumerable<Event> events, int expectedVersion)
{
List<EventDescriptor> eventDescriptors;
if (!_current.TryGetValue(aggregateId, out eventDescriptors))
{
eventDescriptors = new List<EventDescriptor>();
_current.Add(aggregateId, eventDescriptors);
}
else if (eventDescriptors[eventDescriptors.Count - 1].Version != expectedVersion && expectedVersion != -1)
{
throw new ConcurrencyException();
}
var i = expectedVersion;
foreach (var #event in events)
{
i++;
#event.Version = i;
eventDescriptors.Add(new EventDescriptor(aggregateId, #event, i));
_publisher.Publish(#event);
}
}
public List<Event> GetEventsForAggregate(Guid aggregateId)
{
List<EventDescriptor> eventDescriptors;
if (!_current.TryGetValue(aggregateId, out eventDescriptors))
{
throw new AggregateNotFoundException();
}
return eventDescriptors.Select(desc => desc.EventData).ToList();
}
}
public class AggregateNotFoundException : Exception
{
}
public class ConcurrencyException : Exception
{
}
ReadModel.cs
public interface IReadModelFacade
{
IEnumerable<InventoryItemListDto> GetInventoryItems();
InventoryItemDetailsDto GetInventoryItemDetails(Guid id);
}
public class InventoryItemDetailsDto
{
public Guid Id;
public string Name;
public int CurrentCount;
public int Version;
public InventoryItemDetailsDto(Guid id, string name, int currentCount, int version)
{
Id = id;
Name = name;
CurrentCount = currentCount;
Version = version;
}
}
public class InventoryItemListDto
{
public Guid Id;
public string Name;
public InventoryItemListDto(Guid id, string name)
{
Id = id;
Name = name;
}
}
public class InventoryListView : Handles<Inserted>, Handles<Updated>
{
public void Handle(Inserted message)
{
BullShitDatabase.list.Add(new InventoryItemListDto(message.Id, message.Name));
}
public void Handle(Updated message)
{
var item = BullShitDatabase.list.Find(x => x.Id == message.Id);
item.Name = message.NewName;
}
}
public class InvenotryItemDetailView : Handles<Inserted>, Handles<Updated>
{
public void Handle(Inserted message)
{
BullShitDatabase.details.Add(message.Id, new InventoryItemDetailsDto(message.Id, message.Name, 0, 0));
}
public void Handle(Updated message)
{
InventoryItemDetailsDto d = GetDetailsItem(message.Id);
d.Name = message.NewName;
d.Version = message.Version;
}
private InventoryItemDetailsDto GetDetailsItem(Guid id)
{
InventoryItemDetailsDto d;
if (!BullShitDatabase.details.TryGetValue(id, out d))
{
throw new InvalidOperationException("did not find the original inventory this shouldnt happen");
}
return d;
}
}
public class ReadModelFacade : IReadModelFacade
{
public IEnumerable<InventoryItemListDto> GetInventoryItems()
{
return BullShitDatabase.list;
}
public InventoryItemDetailsDto GetInventoryItemDetails(Guid id)
{
return BullShitDatabase.details[id];
}
}
public static class BullShitDatabase
{
public static Dictionary<Guid, InventoryItemDetailsDto> details = new Dictionary<Guid, InventoryItemDetailsDto>();
public static List<InventoryItemListDto> list = new List<InventoryItemListDto>();
}
It should't matter whether you're using EventStore or any other storing mechanism, you should be coding against interfaces (contracts) anyway.
But first things first, you commands IMO are not properly defined, they should be immutable objects which carry data and represent a domain operation (CRUD or not), so why do you have methods defined in the commands?
It is not a problem defining a command as a class, you'll need one in the end, but why don't you have an interface as the base type for all the commands? (SOLID principles)
All the class names (commands/events) have to be meaningful, that said, Update, Delete... don't say much really.
Also I don't see where your service layer is. The service layer should be responsible for handling the commands, so how are you planning to do this?
Bellow you have an example of how I would do it (a tad abstract but it gives you an idea):
// Message definitions
public interface IMessage
{
Guid ID {get; set;}
}
public interface IEvent : IMessage
{ }
public interface ICommand : IMessage
{ }
public class DeleteUserCommand : ICommand
{
public Guid ID {get; set;}
public Guid UserId {get; set;}
}
public class UserDeletedEvent : IEvent
{
public Guid ID {get; set;}
public Guid UserId {get; set;}
}
// Repository definitions
public interface IRepository
{ }
public interface IUserRepository : IRepository
{
void DeleteUser(Guid userId);
}
public UserRepository : IUserRepository
{
public void DeleteUser(Guid userId)
{}
}
// Service definitions
public interface IService
{ }
public class UserService : IService, IHandles<DeleteUserCommand>
{
public IUserRepository UserRepository {get; set;}
public void Handle(DeleteUserCommand deleteUserCommand)
{
UserRepository.DeleteUser(deleteUserCommand.Id)
//raise event
}
}

Categories

Resources