I am wondering how to deal with a situation when inside one service lets say ICompanyService I need to call another method from IUserAccountService. ?
So generally lets say that a Company shouldn't exist without an UserAccount.
The IUserAccount implementation service class looks like this:
public class UserAccountService : CrudService<UserAccount>, IUserAccountService
{
private readonly IRepository<UserAccount> _userAccountRepository;
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
public CompanyService(IRepository<UserAccount> userAccountRepository,
IUnitOfWorkFactory unitOfWorkFactory)
: base(userAccountRepository, unitOfWorkFactory)
{
_userAccRepository = userAccRepository;
}
public int RegisterUser(UserAccount user) {
using (var uow=_unitOfWorkFactory.Create())
{
// Details omitted for brievity
var userId = _userAccountRepository.Create(user);
uow.Commit();
return userId;
}
}
//Other service methods
}
The company ICompanyService implementation:
public class CompanyService : CrudService<Company>, ICompanyService
{
private readonly IRepository<Company> _companyRepository;
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
public CompanyService(IRepository<Company> companyRepository,
IUnitOfWorkFactory unitOfWorkFactory)
: base(companyRepository, unitOfWorkFactory)
{
_companyRepository= companyRepository;
}
public int CreateCompanyWithUserAccount(Company company) {
using (var uow=_unitOfWorkFactory.Create())
{
// Some validation with the company.Details omitted for brievity
// Here I need an instance of IUserAccountService
// Suppose I get it through DI or IoC
var userAccountService = IoC.Resolve<IUserAccountService>();
### // Is such approach good or bad?! ###
var userId = userAccountService.RegisterUser(company.UserAccount);
// Map the user id to the company
company.UserAccount.Id = userId;
var companyId = _companyRepository.Create(company);
uow.Commit();
return companyId;
}
}
//Other service methods
}
ORM under the repository is: NHibernate
Seems you have wrong constructor in UserAccountService implementations: public CompanyService
In CompanyService implementation, you better resolve IUserAccountService dependency right in a constructor, so you do it once per object creation, not each time you call method.
There's no problems with those dependencies. If two objects of IUnitOfWorkFactory implementations are problem -> make a singleton
You could just take a dependency on the IRepository<UserAccount>:
public class CompanyService : CrudService<Company>, ICompanyService
{
private readonly IRepository<Company> _companyRepository;
private readonly IRepository<UserAccount> _userAccountRepository;
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
public CompanyService(IRepository<Company> companyRepository,
IUnitOfWorkFactory unitOfWorkFactory
IRepository<UserAccount> userAccountRepository)
: base(companyRepository, unitOfWorkFactory)
{
_companyRepository= companyRepository;
_userAccountRepository = userAccountRepository;
}
public int CreateCompanyWithUserAccount(Company company) {
using (var uow=_unitOfWorkFactory.Create())
{
// Some validation with the company.Details omitted for brievity
var userId = _userAccountRepository.Create(company.UserAccount);
// Map the user id to the company
company.UserAccount.Id = userId;
var companyId = _companyRepository.Create(company);
uow.Commit();
return companyId;
}
}
//Other service methods
}
IMO, it's better to take a dependency on the repository. After all your company service is creating a company and it needs to do some work in the database, which is what the repositories are for. From what I can see in the code, there's no need to involve the UserAccountService.
Related
I am creating a RESTful api in Net 5, according to the instructions I must create repositories and services that make use of them. The logic must be in the services.
The Services I have are:
SubGroupService
GroupsService
The problem I have is that I generated a circular reference since in GroupsService I need a method of SubGroupsService and SubGroupsService i need a method of GroupsService .
Injecting the GroupsService service into SubGroupsService there is no problem, but injecting SubGroupsService into GroupsService generates the circular reference.
Please can you tell me how to solve this type of problem, since I don't have much experience with dependency injection.
SubGroupService
public class SubGroupService: ISubGroupService
{
private readonly ISubGroupRepository _SubGroupRepository;
private readonly IGroupService _GroupService;
public SubGroupService(
ISubGroupRepository SubGroupRepository,
IGroupService GroupService
{
_SubGroupRepository = SubGroupRepository;
_GroupService = GroupService;
}
public async Task InsertSubGroupService(Subgroup subgroup)
{
var group = await _GroupService.GetGroupService(subgroup.idgroup);
if (group != null)
{
await _SubGroupRepository.InsertSubGroupRepository(subgroup);
}
else
{
throw new BusinessException("This group not exists");
}
}
public async Task<Subgroups> GetSubGroupService(int idgroup)
{
return await _SubGroupRepository.GetSubGroupRepository(idgroup);
}
}
Group Service
public class GroupService : IGroupService
{
private readonly ISubGroupService _SubGroupService;
private readonly IGroupRepository _GroupRepository;
public GroupService(
ISubGroupService SubGroupService,
IGroupRepository GroupRepository)
{
_SubGroupService = SubGroupService;
_GroupRepository = GroupRepository;
}
public async Task<bool> DeleteGroupService(int Idgroup)
{
var existsSubGroup = await _SubGroupRepository(Idgroup);
if(existsSubGroup == null)
{
return await _GroupRepository.DeleteGroupRepository(Idgroup);
}
}
public async Task<Groups> GetGroupService(int Idgroup)
{
return await _GroupRepository.GetGroupRepository(Idgroup);
}
}
Interfaces:
public interface IGroupService
{
Task<Groups> GetGroupsService(int Idgroup);
Task<bool> DeleteGroupService(int Idgroup);
}
public interface ISubGroupService
{
Task<Subgroups> GetSubGroupService(int idsubgrupo);
Task InsertSubgroupService(Subgroup subgroup);
}
You can't use constructor injection in that case. You can switch to property injection:
public class SubGroupService: ISubGroupService
{
private readonly ISubGroupRepository _SubGroupRepository;
public IGroupService GroupService { get; set; }
public SubGroupService(
ISubGroupRepository SubGroupRepository)
{
_SubGroupRepository = SubGroupRepository;
}
// methods of the class
}
public class GroupService : IGroupService
{
public ISubGroupService SubGroupService {get; set;}
private readonly IGroupRepository _GroupRepository;
public GroupService(
IGroupRepository GroupRepository)
{
_GroupRepository = GroupRepository;
}
// methods of the class
}
You'll have to create the objects like this:
IGroupRepository groupRepository = new GroupRepository();
IGroupService groupService = new GroupService(groupRepository);
ISubGroupService subGroupService = new SubGroupService(groupRepository);
groupService.SubGroupSerivce = subGroupService;
subGroupService.GroupService = groupService;
Of course, creation of the objects is now much more complicated. You might put the creation into a facotry method to avoid errors:
public (IGroupService,ISubGroupService) CreateGroupAndSubGroupService()
{
// code from above
}
And it is also advisable to add null checks, because someone might create the objects without initializing the service correctly.
I have a project that supports plugins. As to make plugins unit-testable, they only interact with the main application through interfaces.
The main application provides an implementation to these interfaces. The different components of this application also have dependencies between each others.
I want to limit the amount of interface members by only having the ones needed for plugin development. Problem is, sometimes an implementation needs to call a method that I do not want to expose to the plugins. In a "class" world, I would use the internal keyword for these methods.
Here's a rudimentary example that might be clearer:
interface IUserManager
{
IReadOnlyCollection<IUser> Users { get; }
}
interface IUser
{
string Name { get; }
}
class UserImpl : IUser
{
public string Name { get; }
public void Delete()
{
// ...
}
}
class UserManager : IUserManager
{
IReadOnlyCollection<IUser> Users { get; }
public void DeleteAllUsers()
{
foreach(var user in Users)
{
if(user is UserImpl impl)
{
impl.Delete();
}
}
}
}
class Plugin
{
public Plugin(IUserManager userManager)
{
// I want the plugin to be able to access the user's name, but not its Delete() method
Console.WriteLine(userManager.Users.First().Name);
}
}
class NetworkController
{
private readonly IUserManager _userManager;
public ReceiveDeleteMessage(string name)
{
var user = _userManager.Users.Single(x => x.Name == name);
user.Delete(); // not possible, needs a cast
}
}
But this feels wrong to me... Not only we now have a cast that could fail, we have no way to mock the Delete() function for implementation unit tests. The best thing I could come with is adding an "internal" interface, but I am still stuck with the cast.
interface IInternalUser : IUser
{
void Delete();
}
class UserImpl : IInternalUser
{
public string Name { get; }
public void Delete()
{
}
}
// in UserManager ...
if(user is IInternalUser internalUser)
{
internalUser.Delete();
}
I could settle with this and I think it will be fine, but this little detail makes me feel like I am not taking the best approach. I am looking for better ideas on how to do this.
You can introduce an interface IUserWithDelete such as:
interface IUserWithDelete: IUser
{
void Delete();
}
This interface will not be passed to any plugins, thus they will never see the Delete() method.
Then class UserManager can have an IReadOnlyCollection<IUserWithDelete> field that it exposes as IReadOnlyCollection<IUser>.
The UserImpl class would implement IUserWithDelete, and UserImpl can be internal if you want.
So you would implement UserImpl like so:
class UserImpl : IUserWithDelete
{
public string Name { get; }
public void Delete()
{
// ...
}
}
And class UserManager along the lines of:
class UserManager : IUserManager
{
public UserManager(IReadOnlyCollection<IUserWithDelete> users)
{
_users = users;
}
public IReadOnlyCollection<IUser> Users => _users;
public void DeleteAllUsers()
{
foreach (var user in _users)
{
user.Delete();
}
}
readonly IReadOnlyCollection<IUserWithDelete> _users;
}
No casting is required, and the plugins only see Users as IReadOnlyCollection<IUser> and thus IUserWithDelete is not exposed to them.
Example on .net Fiddle
To answer your amended question:
Firstly, I think that the delete operation should be in the user manager class - after all, that's its job!
Secondly, doing it that way you can introduce another new interface, IUserManagerWithDelete (which can be internal if the implementation of NetworkController is internal) like so:
interface IUserManagerWithDelete: IUserManager
{
bool DeleteUser(string name);
}
Then your UserManager implementation becomes:
class UserManager : IUserManagerWithDelete
{
public UserManager(IReadOnlyCollection<IUserWithDelete> users)
{
_users = users;
}
public IReadOnlyCollection<IUser> Users => _users;
public bool DeleteUser(string name)
{
var user = _users.SingleOrDefault(user => user.Name == name);
user?.Delete();
return user != null;
}
public void DeleteAllUsers()
{
foreach (var user in _users)
{
user.Delete();
}
}
readonly IReadOnlyCollection<IUserWithDelete> _users;
}
And the internal class NetworkController something like:
class NetworkController
{
public NetworkController(IUserManagerWithDelete userManager)
{
_userManager = userManager;
}
public bool ReceiveDeleteMessage(string name)
{
return _userManager.DeleteUser(name);
}
readonly IUserManagerWithDelete _userManager;
}
Note that for illustrative purposes, I've made the return type of DeleteUser() a bool to indicate whether the user was actually deleted (but it will still throw an exception if more than one user with the same name is in the list).
I think I found a solution going further with #matthew-watson's answer
public interface IInternalUserManager : IUserManager
{
new IReadOnlyCollection<IUserWithDelete> Users { get; }
}
public class UserManager : IInternalUserManager
{
public IReadOnlyCollection<IUserWithDelete> Users => _users;
IReadOnlyCollection<IUser> IUserManager.Users => _users;
}
This allows me to inject IInternalUserManager to NetworkController, while using the same object as an IUserManager in the plugin's container without having duplicate property names for the same collection.
interface IDelete
{
void Delete();
}
interface IUser : IDelete
{
string Name { get; }
}
like this ?
interface IUserBehavior : IDelete , ICreate ....
{
IUser Data;
}
IReadOnlyCollection<IUserBehavior> Users { get; }
or this ?
Dears,
I used Automapper IMappingAction to encapsulate Before and After Map Actions into small reusable classes but i can't make my class work with ASPNET Bolierplate Ioc Castle Windsor
configuration.CreateMap<CustomerDto, Customer>()
.AfterMap<CustomerAction>().ReverseMap();
public class CustomerAction : IMappingAction<CustomerDto, Customer>
{
private readonly IObjectMapper _objectMapper;
public CustomerAction(IObjectMapper objectMapper)
{
_objectMapper = objectMapper;
}
public void Process(CustomerDto customerDto, Customer customer)
{
}
}
when my code get execute, i got exception that my class doesn't have parameterless constructor
https://github.com/aspnetzero/aspnet-zero-core/issues/1587#issuecomment-415617774
Do you try this?
cfg.CreateMap<CustomerDto, Customer>().AfterMap((source, destination) =>
{
var action = IocManager.IocContainer.Resolve<CustomerAction>();
action.Process(source, destination);
}).ReverseMap();
public class CustomerAction : IMappingAction<CustomerDto, Customer>, ITransientDependency
{
private readonly IObjectMapper _objectMapper;
public CustomerAction(IObjectMapper objectMapper)
{
_objectMapper = objectMapper;
}
public void Process(CustomerDto customerDto, Customer customer)
{
}
}
I'm using CQRS pattern in my recent project, and used EF code first in my DAL, so I defined some generic CommandHandlers to do Insert/Update/Delete:
public class InsertCommandHandler<TEntity> : ICommandHandler<InsertCommandParameter<TEntity>>
where TEntity : BaseEntity, IAggregateRoot<TEntity>, new()
{
private readonly IUnitOfWork _uow;
public InsertCommandHandler(IUnitOfWork uow)
{
_uow = uow;
}
public void Handle(InsertCommandParameter<TEntity> parameter)
{
var entity = parameter.Entity;
_uow.Repository<TEntity>().Add(entity);
}
}
public interface ICommandParameter
{
}
public abstract class BaseEntityCommandParameter<T> : ICommandParameter
where T : BaseEntity, new()
{
public T Entity { get; set; }
protected BaseEntityCommandParameter()
{
Entity = new T();
}
}
public class InsertCommandParameter<T> : BaseEntityCommandParameter<T> where T : class, new()
{
}
As you see I injected the IUnitOfWork to the InsertCommandHandler constructor.
public interface IUnitOfWork : IDisposable
{
IRepository<T> Repository<T>() where T : BaseEntity, IAggregateRoot<T>,new ();
void Commit();
}
I used Structuremap 3 as my IoC Container, So I defined following conversion to resolve ICommandHandlers for each BaseEntity types(using custom registration conventions for partially closed types):
public class CRUDCommandRegistrationConvention : StructureMap.Graph.IRegistrationConvention
{
private static readonly
Type _openHandlerInterfaceType = typeof(ICommandHandler<>);
private static readonly
Type _openInsertCommandType = typeof(InsertCommandParameter<>);
private static readonly
Type _openInsertCommandHandlerType = typeof(InsertCommandHandler<>);
private static readonly
Type _openUpdateCommandType = typeof(UpdateCommandParameter<>);
private static readonly
Type _openUpdateCommandHandlerType = typeof(UpdateCommandHandler<>);
private static readonly
Type _openDeleteCommandType = typeof(DeleteCommandParameter<>);
private static readonly
Type _openDeleteCommandHandlerType = typeof(DeleteCommandHandler<>);
public void Process(Type type, Registry registry)
{
if (!type.IsAbstract && typeof(BaseEntity).IsAssignableFrom(type))
if (type.GetInterfaces()
.Any(x => x.IsGenericType && x.GetGenericTypeDefinition()
== typeof(IAggregateRoot<>)))
{
Type closedInsertCommandType = _openInsertCommandType.MakeGenericType(type);
Type closedInsertCommandHandlerType = _openInsertCommandHandlerType.MakeGenericType(type);
Type closedUpdateCommandType = _openUpdateCommandType.MakeGenericType(type);
Type closedUpdateCommandHandlerType = _openUpdateCommandHandlerType.MakeGenericType(type);
Type closedDeleteCommandType = _openDeleteCommandType.MakeGenericType(type);
Type closedDeleteCommandHandlerType = _openDeleteCommandHandlerType.MakeGenericType(type);
Type insertclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedInsertCommandType);
Type updateclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedUpdateCommandType);
Type deleteclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedDeleteCommandType);
registry.For(insertclosedHandlerInterfaceType).Use(closedInsertCommandHandlerType);
registry.For(updateclosedHandlerInterfaceType).Use(closedUpdateCommandHandlerType);
registry.For(deleteclosedHandlerInterfaceType).Use(closedDeleteCommandHandlerType);
}
}
}
And used it in my CompositionRoot:
public static class ApplicationConfiguration
{
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(s =>
{
s.AssemblyContainingType(typeof(ICommandHandler<>));
s.AssemblyContainingType(typeof(Order));
s.AssemblyContainingType(typeof(FindOrderByIdQueryHandler));
s.WithDefaultConventions();
x.For(typeof(IUnitOfWork))
.Use(typeof(EfUnitOfWork<SaleDBContext>))
.Named("SaleDBContext")
.SetLifecycleTo((Lifecycles.Singleton));
s.Convention<CRUDCommandRegistrationConvention>();
});
});
return ObjectFactory.Container;
}
public static T Resolve<T>()
{
return ObjectFactory.GetInstance<T>();
}
}
I registered EfUnitOfWork<SaleDBContext> for IUnitOfWork, but I want to use separate DbContext per each module in my solution(Bounded context). For example my sale module has its own DbContext, HR module has its own DbContext and etc, and above registration conversion, only register EfUnitOfWork<SaleDBContext> as my IUnitOfWork.
I have some modules(Solution Folders in Visual Studio) in my solution and each module has 3 layer(3 class library projects):
My modules has following structure(each module has 3 assemblies) for example:
SaleModule:
----Application
----Domain (Entities , ...) //Order, Customer,...
----DAL (DbContext ,...) //SaleDbContext
HRModule:
----Application
----Domain (Entities , ...) // Employee, OrganizationUnit, ...
----DAL (DbContext ,...)//HRDbContext
InfrastructureModule:
----Application (ICommandHandler,IQueryHandler,...)
----Domain
----DAL
The InsertCommandHandler<T> puts in Infrastructure Module.
When I use the InsertCommanHandler<T> I want it uses corresponding module's DbContext as IUnitOfWork. for example, I want the InsertCommandHandler<Order> uses SaleDbContext as it's IUnitOfWork and InsertCommandHandler<Employee> uses HRDbContext as it's IUnitOfWork.
[UPDATED]
This is a sample of cunsumers code that IoC containar should provide SaleDbContext for Consumer1 and HRDbContext for Consumer2:
public class Consumer1
{
ICommandHandler<InsertCommandParameter<Order>> _insertCommandHandler;
public Consumer1(ICommandHandler<InsertCommandParameter<Order>> insertCommandHandler)
{
_insertCommandHandler = insertCommandHandler;
}
public void DoInsert()
{
var command = new InsertCommandParameter<Order>();
command.Entity = new Order(){
Number = 'ord-01',
// other properties
};
insertCommandHandler.Handle(command); //this query handler should use SaleDbContext
}
}
public class Consumer2
{
ICommandHandler<InsertCommandParameter<Employee>> _insertCommandHandler;
public Consumer2(ICommandHandler<InsertCommandParameter<Employee>> insertCommandHandler)
{
_insertCommandHandler = insertCommandHandler;
}
public void DoInsert()
{
var command = new InsertCommandParameter<Employee>();
command.Entity = new Employee(){
EmployeeNumber = 'Emp1',
// other properties
};
insertCommandHandler.Handle(command); //this query handler should use HRDbContext
}
}
How could I do that in my composition root using StructureMap?
You can make IUnitOfWork generic as in IUnitOfWork<TConnection>. This allows each Repository to stipulate which UnitOfWork it requires, ideally using constructor injection, e.g.
public class InsertCommandHandler : ICommandHandler<Order>
{
public InsertCommandHandler(IUnitOfWork<SalesDbContext> salesUnitOfWork)
{
// ...
}
}
However, you probably don't want to reference the DbContext in each handler so you should define an abstraction to avoid such a dependency.
Start with a simple interface that all DbContext wrapper classes will implement
public interface IConnection
{
DbContext Context { get; }
}
Update IUnitOfWork accordingly
public interface IUnitOfWork<TConnection> where TConnection : IConnection { }
Here's an example wrapper
public class SalesConnection : IConnection
{
private readonly DbContext context;
public SalesConnection()
{
this.context = new SalesDbContext();
}
public DbContext Context { get { return this.context; } }
}
And here's what the updated command handler will look like
public class InsertCommandHandler : ICommandHandler<Order>
{
public InsertCommandHandler(IUnitOfWork<SalesConnection> salesUnitOfWork)
{
// ...
}
}
UPDATE
The logical thing to do for common handlers is to have one per logical domain (i.e. per DbContext), for example SalesInsertCommandHandler, HRInsertCommandHandler
public class SalesInsertCommandHandler<TCommand> : ICommandHandler<TCommand>
{
public SalesInsertCommandHandler(IUnitOfWork<SalesConnection> unitOfWork)
{
}
}
This adheres to the separation of concerns principle and gives you extra flexibility when you come to decorate your concerns with different aspects (tracing, retry logic etc.)
All command handlers can of course inherit from a single common (abstract) command handler.
public abstract class CommandHandler<TConnection, TCommand> :
ICommandHandler<TCommand>
where TConnection : IConnection
{
private readonly IUnitOfWork<TConnection> unitOfWork;
public CommandHandler(IUnitOfWork<TConnection> unitOfWork)
{
this.unitOfWork = unitOfWork;
}
}
public class SalesInsertCommandHandler<TCommand> :
CommandHandler<SalesConnection, TCommand>
{
}
What is the best way to handle a situation where you're using IoC but there is a static method in it along with the other methods like the following:
public partial class ShoppingCart
{
private IDatabaseFactory _storeDB;
public ShoppingCart(IDatabaseFactory storeDB)
{
_storeDB = storeDB;
}
private string ShoppingCartId { get; set; }
public static ShoppingCart GetCart(HttpContextBase context)
{
var cart = new ShoppingCart(WHATGOESHERE?);
cart.ShoppingCartId = cart.GetCartId(context);
return cart;
}
public int OtherMethod()
{
...
}
}
The static GetCart method is an Ambient Context. It's a bad idea, especially to have such a method at the level of your domain model. Try refactoring it to an abstract factory:
public interface IShoppingCartFactory
{
ShoppingCart GetCartForCurrentUser();
}
You can inject the IShoppingCartFactory in services that need it (but not in your entities, it's better to keep your entities clean). Now you can define an implementation and register it in your IoC configuration. Here's an example of such an implementation:
public class HttpShoppingCartFactory : IShoppingCartFactory
{
private readonly IShoppingUnitOfWorkFactory uowFactory;
public HttpShoppingCartFactory(
IShoppingUnitOfWorkFactory uowFactory)
{
this.uowFactory = uowFactory;
}
public ShoppingCart GetCartForCurrentUser()
{
int userId = (int)HttpContext.Current.Session["userId"];
using (var unitOfWork = this.uowFactory.CreateNew())
{
return unitOfWork.ShoppingCards
.FirstOrDefault(c => c.User.Id == userId);
}
}
}
It would be even better to separate the getting the user context from the shopping card factory. For instance, you yould inject a IUserContextFactory in the shopping card factory, making it independant on ASP.NET.
IMO you should refactor it, making it to look like this:
public class ShoppingCartService {
private readonly IDatabaseFactory _storeDB;
public ShoppingCartService(IDatabaseFactory storeDB) {
_storeDB = storeDB
}
public ShoppingCart GetCart(IdType cartId)
{
var cart = new ShoppingCart(_storeDB);
cart.ShoppingCartId = cartId;
return cart;
}
}
public partial class ShoppingCart
{
private IDatabaseFactory _storeDB;
public ShoppingCart(IDatabaseFactory storeDB)
{
_storeDB = storeDB;
}
private string ShoppingCartId { get; set; }
public int OtherMethod()
{
...
}
}
This way, you are moving responsibility to get the current shopping cart from a static method to a service class you can inject in the presentation layer.