Repository/Service Pattern Issues .NET Core - c#

Having some architecture issues that I'm trying to work through. I need to find a better way to do what I'm trying to do.
Below is a brief mockup of how my services/repos look. My problem is I am getting a circular reference when activating them. The problem is there is code in each service that I need for example in the LoadService I may need to trigger a method in the CustomerService and vice versa.
Need help to understand the best approach here. I am trying to get these services in a SRP as much as possible.
LoadRepository
public class LoadRepository
{
private readonly DBContext _DBContext;
public LoadRepository(DBContext DBContext)
{
_DBContext = DBContext;
}
public override DbSet<LoadEntity> LoadDbSet()
{
return _DBContext.Load;
}
}
LoadService
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly ICustomerService _customerService;
public LoadService(
LoadRepository loadRepository,
ICustomerService customerService
)
{
_loadRepository = loadRepository;
_customerService = customerService;
}
}
CustomerRepository
public class CustomerRepository
{
private readonly DBContext _DBContext;
public CustomerRepository(DBContext DBContext)
{
_DBContext = DBContext;
}
public override DbSet<CustomerEntity> LoadDbSet()
{
return _DBContext.Customer;
}
}
CustomerService
public class CustomerService
{
private readonly CustomerRepository _customerRepository;
private readonly ILoadService _loadService;
public CustomerService(
CustomerRepository customerRepository,
ILoadService loadService
)
{
_customerRepository = customerRepository;
_loadService = loadService;
}
}

In my personal experience it is better to avoid dependencies on the same level referencing each other. Move common functionality into some helper classes and/or inject all needed repositories into the corresponding services. For example :
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly CustomerRepository _customerRepository;
public LoadService(
LoadRepository loadRepository,
CustomerRepository customerRepository
)
{
_loadRepository = loadRepository;
_customerRepository = customerService;
}
}
Another approach to mitigate the problem (if currently refactoring is to much of headache) - use lazy injection via factories, for example something like the following using factory via Func:
// default DI does not provide automatic Func registration
Services.AddScoped<Func<ICustomerService>>(sp => () => sp.GetRequiredService<>(ICustomerService))
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly Func<ICustomerService> _customerServiceFactory;
public LoadService(
LoadRepository loadRepository,
Func<ICustomerService> customerService
)
{
_loadRepository = loadRepository;
_customerServiceFactory = customerService;
}
}
And when it is needed invoke the factory - _customerServiceFactory().SomeMethod(). Though note that this method can result in SO if you have cycle in invocations (i.e. ICustomerService.Foo() calls ILoadService.Bar() which calls ICustomerService.Foo()) which can be caught only in runtime.

Related

Can we call a parameterized constructor from a parameterless constructor?

For example I have class like this
public class ABC
{
private readonly IMemoryCache _cache;
private readonly IConfiguration _config;
private readonly IDistributedCache _distributedCache;
public ABC(IMemoryCache memoryCache, IConfiguration config, IDistributedCache distributedCache)
{
_cache = memoryCache;
_config = config;
_distributedCache = distributedCache;
}
public ABC() : this(IMemoryCache , IConfiguration ,IDistributedCache )
{
}
}
As you can see that I have tried to call a Parameterized constructor from a Parameter-less constructor, but that's not possible. Is there any other way to achieve this concept?
You need to pass in concrete implementations of those interfaces, It's just like calling a method. There is nothing magical about this() syntax apart from where it appears. For example if you have a default implementation of IMemoryCache implemented in class DefaultMemoryCache you can just 'new that up' and pass it in:
public ABC() : this(new DefaultMemoryCache(), etc.)
{
}
Alternatively, you can use a static factory method if constructing these dependencies is a bit too complicated:
public static ABC CreateNew()
{
var others = ...
var cache = new DefaultCache(others, etc.)
...
return new ABC(cache, etc.);
}
But if you want to be able to use the interface as your input, this is what you can do: (Now, this is just an example to make a point, I do not recommend doing this since it would be very confusing and fragile)
public ABC() : this
(
(IMemoryCache) Activator.CreateInstance
(
Assembly.GetExecutingAssembly().GetTypes().First
(
t => typeof(IMemoryCache).IsAssignableFrom(t) && !t.IsInterface
)
)
)
{
}
The reflection code snippet above, in essence, what a dependency injection library would do, and you might want to consider using one if your project is suitable for it.
One last thing, just to have a complete answer, of course, you can also implement a body in your overloaded contractors:
public class ABC
{
private readonly ICache _cache;
public ABC()
{
_cache = new Cache();
}
public ABC(ICache cache)
{
_cache = cache;
}
}
: this() syntax is only required if you want to call other constructors in the same class for code reuse.
use instances not types. create an instance of what ever class fulfills your Interface.
public class ABC
{
private readonly IMemoryCache _cache;
private readonly IConfiguration _config;
private readonly IDistributedCache _distributedCache;
public ABC(IMemoryCache memoryCache, IConfiguration config, IDistributedCache distributedCache)
{
_cache = memoryCache;
_config = config;
_distributedCache = distributedCache;
}
public ABC() : this(new MemoryCache(), new Configuration(), new DistributedCache() )
{
}
}

How to use a factory to instantiate an interface

I have a factory to create a Generic service:
public static class AdPersisterFactory<TEntity>
where TEntity : AdBase
{
public static AdPersister<TEntity> Create(ApplicationDbContext dbContext)
{
AdRepository<TEntity> adRepository = new AdRepository<TEntity>(dbContext);
IAdImagePersister s3AdImagePersister = new S3AdImagePersister();
AdPersister<TEntity> adPersister = new AdPersister<TEntity>(adRepository, s3AdImagePersister);
return adPersister;
}
}
I want to use ninject (version 3), how can I bind IAdPersister to an instance that the above factory creates... This is my DI Code:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
// I have tried the following which does not compile
// kernel.Bind(typeof(IAdPersister<>)).ToMethod(ctx => AdPersisterFactory<>.Create(new ApplicationDbContext()));
}
This is for an ASp.NET MVC application, so ideally I don't want to use new ApplicationDbContext but use the same ApplicationDbContext which exists in RequestScope.
I have also seen Ninject.Extensions.Factory but I am not sure how/if I can use it in this scenario.
If you are willing to refactor to a more SOLID approach and AdRepository<TEntity> has a backing interface like
public class AdRepository<TEntity> : IAdRepository<TEntity>
where TEntity : AdBase {
public AdRepository(ApplicationDbContext dbContext) {
//...
}
}
And assuming...
public class AdPersister<TEntity> : IAdPersister<TEntity>
where TEntity : AdBase {
public AdPersister(IAdRepository<TEntity> adRepository, IAdImagePersister imagePersister) {
//...
}
//...
}
Then a way to create your open generic dependency would look like
private static void RegisterServices(IKernel kernel) {
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind<IAdImagePersister>().To<S3AdImagePersister>();
//Open generic bind for repository and ad persister
kernel.Bind(typeof(IAdRepository<>)).To(typeof(AdRepository<>));
kernel.Bind(typeof(IAdPersister<>)).To(typeof(AdPersister<>));
}
Now where ever the persister is needed you simple inject the closed type as
ctor(IAdPersister<Foo> fooPersister)
And the necessary dependencies will be resolved and injected by the container.
There really is no need for that static factory.
UPDATE
Based on comment I still advise to not have the static factory.
If you want to keep implementation details internal to your library then make the factory an instance class
public class AdPersisterFactory<TEntity> : IAdPersisterFactory<TEntity>
where TEntity : AdBase {
private readonly ApplicationDbContext dbContext;
public AdPersisterFactory(ApplicationDbContext dbContext) {
this.dbContext = dbContext;
}
public IAdPersister<TEntity> Create() {
AdRepository<TEntity> adRepository = new AdRepository<TEntity>(dbContext);
IAdImagePersister s3AdImagePersister = new S3AdImagePersister();
AdPersister<TEntity> adPersister = new AdPersister<TEntity>(adRepository, s3AdImagePersister);
return adPersister;
}
}
That can be registered as an open generic in your composition root.
private static void RegisterServices(IKernel kernel) {
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind(typeof(IAdPersisterFactory<>)).To(typeof(AdPersisterFactory<>));
}
and used
ctor(IAdPersisterFactory<Foo> fooPersisterFactory) {
IAdPersister<Foo> fooPersister = fooPersisterFactory.Create();
//...
}

Unit Of Work and dependency Injection

I want to implement Unit Of Work design pattern in my project and from this article the dbContext and all repositories are initialized in the UnitOfWork class , and I saw there is no place for dependency injection here . Is there is a way to use dpendency injection or there is no need and why?
Here is the implementation of unit of work if you are using DbContext :
class UnitOfWork : IDisposable
{
private readonly DbContext _yourDbContext;
public UnitOfWork(DbContext yourDbContext)
{
_yourDbContext = yourDbContext
}
public void Save()
{
_yourDbContext.Save();
}
void Dispose()
{
_yourDbContext = null;
}
}
public interface IUnitOfWork
{
void Save();
}
Uses :
IUnitOfWork _uow;
_yourStudentRepository.Add(Student);
_yourAddressRepository.Add(Address);
_uow.Save();
You can create the DI if you want.
public class UnitOfWork : IDisposable
{
private ISchoolContext _context;
public UnitOfWork(ISchoolContext context)
{
_context = context;
}
}
Then in your controller you can inject the Unit of Work too in the same way.
You can do all that stuff, now the question is if you need that fancy DI, personally I would, but that is up to you and your needs.

Using Simple Injector with Unit Of Work & Repository Pattern in Windows Form

I'm trying to implement IoC in my windows form application. My choice fell on Simple Injector, because it's fast and lightweight. I also implement unit of work and repository pattern in my apps. Here is the structure:
DbContext:
public class MemberContext : DbContext
{
public MemberContext()
: base("Name=MemberContext")
{ }
public DbSet<Member> Members { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();\
}
}
Model:
public class Member
{
public int MemberID { get; set; }
public string Name { get; set; }
}
GenericRepository:
public abstract class GenericRepository<TEntity> : IGenericRepository<TEntity>
where TEntity : class
{
internal DbContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(DbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
}
MemberRepository:
public class MemberRepository : GenericRepository<Member>, IMemberRepository
{
public MemberRepository(DbContext context)
: base(context)
{ }
}
UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
public DbContext context;
public UnitOfWork(DbContext context)
{
this.context = context;
}
public void SaveChanges()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
MemberService:
public class MemberService : IMemberService
{
private readonly IUnitOfWork unitOfWork;
private readonly IMemberRepository memberRepository;
public MemberService(IUnitOfWork unitOfWork, IMemberRepository memberRepository)
{
this.unitOfWork = unitOfWork;
this.memberRepository = memberRepository;
}
public void Save(Member member)
{
Save(new List<Member> { member });
}
public void Save(List<Member> members)
{
members.ForEach(m =>
{
if (m.MemberID == default(int))
{
memberRepository.Insert(m);
}
});
unitOfWork.SaveChanges();
}
}
In Member Form I only add a textbox to input member name and a button to save to database. This is the code in member form:
frmMember:
public partial class frmMember : Form
{
private readonly IMemberService memberService;
public frmMember(IMemberService memberService)
{
InitializeComponent();
this.memberService = memberService;
}
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
memberService.Save(member);
}
}
I implement the SimpleInjector (refer to http://simpleinjector.readthedocs.org/en/latest/windowsformsintegration.html) in Program.cs as seen in the code below:
static class Program
{
private static Container container;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
Application.Run(new frmMember((MemberService)container.GetInstance(typeof(IMemberService))));
}
private static void Bootstrap()
{
container = new Container();
container.RegisterSingle<IMemberRepository, MemberRepository>();
container.Register<IMemberService, MemberService>();
container.Register<DbContext, MemberContext>();
container.Register<IUnitOfWork, UnitOfWork>();
container.Verify();
}
}
When I run the program and add a member, it doesn't save to database. If I changed container.Register to container.RegisterSingle, it will save to database. From the documentation, RegisterSingle will make my class to be a Singleton. I can't using RegisterLifeTimeScope because it will generate an error
"The registered delegate for type IMemberService threw an exception. The IUnitOfWork is registered as 'Lifetime Scope' lifestyle, but the instance is requested outside the context of a Lifetime Scope"
1) How to use SimpleInjector in Windows Form with UnitOfWork & Repository pattern?
2) Do I implement the patterns correctly?
The problem you have is the difference in lifestyles between your service, repository, unitofwork and dbcontext.
Because the MemberRepository has a Singleton lifestyle, Simple Injector will create one instance which will be reused for the duration of the application, which could be days, even weeks or months with a WinForms application. The direct consequence from registering the MemberRepository as Singleton is that all dependencies of this class will become Singletons as well, no matter what lifestyle is used in the registration. This is a common problem called Captive Dependency.
As a side note: The diagnostic services of Simple Injector are able to spot this configuration mistake and will show/throw a Potential Lifestyle Mismatch warning.
So the MemberRepository is Singleton and has one and the same DbContext throughout the application lifetime. But the UnitOfWork, which has a dependency also on DbContext will receive a different instance of the DbContext, because the registration for DbContext is Transient. This context will, in your example, never save the newly created Member because this DbContext does not have any newly created Member, the member is created in a different DbContext.
When you change the registration of DbContext to RegisterSingleton it will start working, because now every service, class or whatever depending on DbContext will get the same instance.
But this is certainly not the solution because having one DbContext for the lifetime of the application will get you into trouble, as you probably already know. This is explained in great detail in this post.
The solution you need is using a Scoped instance of the DbContext, which you already tried. You are missing some information on how to use the lifetime scope feature of Simple Injector (and most of the other containers out there). When using a Scoped lifestyle there must be an active scope as the exception message clearly states. Starting a lifetime scope is pretty simple:
using (ThreadScopedLifestyle.BeginScope(container))
{
// all instances resolved within this scope
// with a ThreadScopedLifestyleLifestyle
// will be the same instance
}
You can read in detail here.
Changing the registrations to:
var container = new Container();
container.Options.DefaultScopedLifestyle = new ThreadScopedLifestyle();
container.Register<IMemberRepository, MemberRepository>(Lifestyle.Scoped);
container.Register<IMemberService, MemberService>(Lifestyle.Scoped);
container.Register<DbContext, MemberContext>(Lifestyle.Scoped);
container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
and changing the code from btnSaveClick() to:
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
using (ThreadScopedLifestyle.BeginScope(container))
{
var memberService = container.GetInstance<IMemberService>();
memberService.Save(member);
}
}
is basically what you need.
But we have now introduced a new problem. We are now using the Service Locator anti pattern to get a Scoped instance of the IMemberService implementation. Therefore we need some infrastructural object which will handle this for us as a Cross-Cutting Concern in the application. A Decorator is a perfect way to implement this. See also here. This will look like:
public class ThreadScopedMemberServiceDecorator : IMemberService
{
private readonly Func<IMemberService> decorateeFactory;
private readonly Container container;
public ThreadScopedMemberServiceDecorator(Func<IMemberService> decorateeFactory,
Container container)
{
this.decorateeFactory = decorateeFactory;
this.container = container;
}
public void Save(List<Member> members)
{
using (ThreadScopedLifestyle.BeginScope(container))
{
IMemberService service = this.decorateeFactory.Invoke();
service.Save(members);
}
}
}
You now register this as a (Singleton) Decorator in the Simple Injector Container like this:
container.RegisterDecorator(
typeof(IMemberService),
typeof(ThreadScopedMemberServiceDecorator),
Lifestyle.Singleton);
The container will provide a class which depends on IMemberService with this ThreadScopedMemberServiceDecorator. In this the container will inject a Func<IMemberService> which, when invoked, will return an instance from the container using the configured lifestyle.
Adding this Decorator (and its registration) and changing the lifestyles will fix the issue from your example.
I expect however that your application will in the end have an IMemberService, IUserService, ICustomerService, etc... So you need a decorator for each and every IXXXService, not very DRY if you ask me. If all services will implement Save(List<T> items) you could consider creating an open generic interface:
public interface IService<T>
{
void Save(List<T> items);
}
public class MemberService : IService<Member>
{
// same code as before
}
You register all implementations in one line using Batch-Registration:
container.Register(typeof(IService<>),
new[] { Assembly.GetExecutingAssembly() },
Lifestyle.Scoped);
And you can wrap all these instances into a single open generic implementation of the above mentioned ThreadScopedServiceDecorator.
It would IMO even be better to use the command / handler pattern (you should really read the link!) for this type of work. In very short: In this pattern every use case is translated to a message object (a command) which is handled by a single command handler, which can be decorated by e.g. a SaveChangesCommandHandlerDecorator and a ThreadScopedCommandHandlerDecorator and LoggingDecorator and so on.
Your example would then look like:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
public class CreateMemberCommand
{
public string MemberName { get; set; }
}
With the following handlers:
public class CreateMemberCommandHandler : ICommandHandler<CreateMemberCommand>
{
//notice that the need for MemberRepository is zero IMO
private readonly IGenericRepository<Member> memberRepository;
public CreateMemberCommandHandler(IGenericRepository<Member> memberRepository)
{
this.memberRepository = memberRepository;
}
public void Handle(CreateMemberCommand command)
{
var member = new Member { Name = command.MemberName };
this.memberRepository.Insert(member);
}
}
public class SaveChangesCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratee;
private DbContext db;
public SaveChangesCommandHandlerDecorator(
ICommandHandler<TCommand> decoratee, DbContext db)
{
this.decoratee = decoratee;
this.db = db;
}
public void Handle(TCommand command)
{
this.decoratee.Handle(command);
this.db.SaveChanges();
}
}
And the form can now depend on ICommandHandler<T>:
public partial class frmMember : Form
{
private readonly ICommandHandler<CreateMemberCommand> commandHandler;
public frmMember(ICommandHandler<CreateMemberCommand> commandHandler)
{
InitializeComponent();
this.commandHandler = commandHandler;
}
private void btnSave_Click(object sender, EventArgs e)
{
this.commandHandler.Handle(
new CreateMemberCommand { MemberName = txtName.Text });
}
}
This can all be registered as follows:
container.Register(typeof(IGenericRepository<>),
typeof(GenericRepository<>));
container.Register(typeof(ICommandHandler<>),
new[] { Assembly.GetExecutingAssembly() });
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(SaveChangesCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(ThreadScopedCommandHandlerDecorator<>),
Lifestyle.Singleton);
This design will remove the need for UnitOfWork and a (specific) service completely.

Injecting repository dependencies into a Unit of Work

I'm trying to employ the Repository and Unit of Work patterns in my asp.net MVC project, however I'm having difficulty figuring out how to pass Repository dependencies to the Unit of Work. The general standard structure of the Unit of Work seems to be the following:
public class UnitOfWork : IUnitOfWork
{
private ICustomerRepository _customerRepository;
public ICustomerRepository CustomerRepository
{
get
{
if (this._customerRepository == null)
{
this._customerRepository = new CustomerRepository(someContext);
}
return _customerRepository;
}
}
}
Specifically, what's confusing me is this line:
this._customerRepository = new CustomerRepository(someContext);
By defining interfaces for repositories, isn't the whole idea about being able to inject Repository dependencies into the UoW as time progresses and business needs change? If so, why does almost every implementation I see online do the above? In this implementation how are we supposed to pass a new instance of ICustomerRepository to the UoW? Surely we would need to also change code in the UoW and isn't that against the open close principle? How would I inject repositories to my UoW?
I've look around SO, and this question seems to have been asked before, but I'm still having a hard time trying to understand the proposed solution (a facade service).
There are two common ways to get an instance of your CustomerRepository.
First approach is known as constructor injection which is a simple parameter in your constructur e.g.
public class UnitOfWork : IUnitOfWork
{
public UnitOfWork(ICustomerRepository repository)
{
_customerRepository = repository;
}
private ICustomerRepository _customerRepository;
public ICustomerRepository CustomerRepository
{
get
{
if (this._customerRepository == null)
{
throw new ArgumentException("Missing repository");
}
return _customerRepository;
}
}
}
The second and more flexible way is to use an IoC Framework like Structuremap, Unity, Ninject... and so on.
Here's an example of Structuremap:
public class UnitOfWork : IUnitOfWork
{
private ICustomerRepository _customerRepository;
public ICustomerRepository CustomerRepository
{
get
{
if (this._customerRepository == null)
{
_customerRepository = ObjectFactory.GetInstance<ICustomerRepository>();
}
return _customerRepository;
}
}
}
Additionaly you need a configuraiton class to tell Structuremap which class to instantiate which could simply look like this:
public static class RepositoryRegistry
{
internal static void DefaultConfiguration(Registry registry)
{
registry.For<ICustomerRepository>().Use<CustomerRepository>();
}
}

Categories

Resources