Constructor Injection and when to use a Service Locator - dependency-injection

I'm struggling to understand parts of StructureMap's usage.
In particular, in the documentation a statement is made regarding a common anti-pattern, the use of StructureMap as a Service Locator only instead of constructor injection (code samples straight from Structuremap documentation):
public ShippingScreenPresenter()
{
_service = ObjectFactory.GetInstance<IShippingService>();
_repository = ObjectFactory.GetInstance<IRepository>();
}
instead of:
public ShippingScreenPresenter(IShippingService service, IRepository repository)
{
_service = service;
_repository = repository;
}
This is fine for a very short object graph, but when dealing with objects many levels deep, does this imply that you should pass down all the dependencies required by the deeper objects right from the top? Surely this breaks encapsulation and exposes too much information about the implementation of deeper objects.
Let's say I'm using the Active Record pattern, so my record needs access to a data repository to be able to save and load itself. If this record is loaded inside an object, does that object call ObjectFactory.CreateInstance() and pass it into the active record's constructor? What if that object is inside another object. Does it take the IRepository in as its own parameter from further up? That would expose to the parent object the fact that we're access the data repository at this point, something the outer object probably shouldn't know.
public class OuterClass
{
public OuterClass(IRepository repository)
{
// Why should I know that ThingThatNeedsRecord needs a repository?
// that smells like exposed implementation to me, especially since
// ThingThatNeedsRecord doesn't use the repo itself, but passes it
// to the record.
// Also where do I create repository? Have to instantiate it somewhere
// up the chain of objects
ThingThatNeedsRecord thing = new ThingThatNeedsRecord(repository);
thing.GetAnswer("question");
}
}
public class ThingThatNeedsRecord
{
public ThingThatNeedsRecord(IRepository repository)
{
this.repository = repository;
}
public string GetAnswer(string someParam)
{
// create activeRecord(s) and process, returning some result
// part of which contains:
ActiveRecord record = new ActiveRecord(repository, key);
}
private IRepository repository;
}
public class ActiveRecord
{
public ActiveRecord(IRepository repository)
{
this.repository = repository;
}
public ActiveRecord(IRepository repository, int primaryKey);
{
this.repositry = repository;
Load(primaryKey);
}
public void Save();
private void Load(int primaryKey)
{
this.primaryKey = primaryKey;
// access the database via the repository and set someData
}
private IRepository repository;
private int primaryKey;
private string someData;
}
Any thoughts would be appreciated.
Simon
EDIT:
Opinion seems to be that the injection should start at the top layer. ActiveRecord would be injected into ThingThatNeedsRecord which is injected into OuterClass.
The problem with this would be that if ActiveRecord needs to be instantiated with a run-time parameter (the id of the record to retrieve for example). If I'm injecting ActiveRecord into ThingThatNeedsRecord right at the top, I somehow have to figure out what id needs to be at that point (which exposes the top layer to implementation which it shouldn't) or I have to have a partially constructed ActiveRecord and set the Id later on. This becomes more complicated if I need N records and won't know until execution of logic inside ThingThatNeedsRecord.

Inversion of Control is like violence. If it doesn't solve your problem, you're not using enough of it. Or something like that.
More to the point, I think your OuterClass should have ThingThatNeedsRecord injected into it via constructor injection. Likewise ThingThatNeedsRecord should have ActiveRecord injected into it. Not only will this solve your immediate problem, but it will make your code more modular and testable as well.

Related

How to resolve a DI class in a class library with .NET Core?

I understand the basics of DI in .NET Core, but I'm having trouble figuring out how to use it with multiple projects. Imagine I'm setting up a database context in the Startup class of ASP.NET Core:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<GalleryDb>();
}
I know how to access that context in an API controller:
public class AlbumController : Microsoft.AspNetCore.Mvc.Controller
{
private GalleryDb _ctx;
public AlbumController(GalleryDb ctx)
{
_ctx = ctx;
}
}
But what does one do when there are many layers and functions between the API controller and the data access class? Eventually the code reaches my repository class, which is the one that actually requires the context. It looks like this:
public class AlbumRepository
{
private GalleryDb _ctx;
public AlbumRepository(GalleryDb ctx)
{
_ctx = ctx;
}
public void Save(AlbumEntity entity)
{
// Use _ctx to persist to DB.
}
}
I understand that I could pass the context from the API entry point all the way down, but that seems like an anti-pattern because it means passing it as a parameter through multiple classes and functions that have no interest in it.
Instead, I'd like to do something like this at the point where I invoke the repository class:
public void Save(AlbumEntity album)
{
var ctx = DependencyResolver.GetInstance<GalleryDb>();
var repo = new AlbumRepository(ctx);
repo.Save(album);
}
I believe some DI frameworks have something like this, but I'm trying to figure out how to do it with native .NET Core 2.0. Is this possible? What is the best practice? I found one thread (ASP.NET Core DependencyResolver) talk about using IServiceProvider but the implication was that this was not a desirable solution.
I'm hoping whatever the solution is, I can extend it to apply to other DI classes like ASP.NET Identity's RoleManager and SignInManager.
The key breakthrough chris-pratt helped me understand is that the only way this works is to use DI through all the layers. For example, down in the data layer I get a DB context through DI:
public class AlbumRepository
{
private GalleryDb _ctx;
public AlbumRepository(GalleryDb ctx)
{
_ctx = ctx;
}
}
In the business layer I use DI to get a reference to the data layer:
public class Album
{
private AlbumRepository _repo;
public Album(AlbumRepository repo)
{
_repo = repo;
}
}
Then, in the web layer, I use DI to get a reference to the business layer class:
[Route("api/[controller]")]
public class AlbumController : Microsoft.AspNetCore.Mvc.Controller
{
private Album _album;
public AlbumController (Album album)
{
_album = album;
}
}
By using DI through every layer, the DI system is able to construct all the necessary classes at the point where they are needed.
This requirement has a profound impact on the architecture of an application, and I now realize that my initial hope to tweak an existing, non-DI app to start using DI for the DB context is a major undertaking.
I understand that I could pass the context from the API entry point all the way down, but that seems like an anti-pattern because it means passing it as a parameter through multiple classes and functions that have no interest in it.
No, that's not an anti-pattern. That's how you should do it. However, the bit about "classes and functions that have no interest in it" makes no sense.
Simply, if you're working with something like a repository that wraps a DbContext (a horrible idea, by the way, but we'll put a pin in that), then you shouldn't ever be dealing directly with that DbContext. Instead, you should be injecting your repository into your controllers and then simply let the context be injected into that:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<GalleryDb>();
services.AddScoped<AlbumRepository>();
}
Since ASP.NET Core knows how to inject GalleryDb, and AlbumRepository takes GalleryDb as a constructor param, you simply register AlbumRepository for injection as well (using a "scoped" or request lifetime).
Now, you can inject AlbumRepository the same way you're currently injecting the context:
public class AlbumController : Microsoft.AspNetCore.Mvc.Controller
{
private AlbumRepository _repo;
public AlbumController(AlbumRepository repo)
{
_repo = repo;
}
}
Where this starts to get tricky is when you have many repositories, especially if you have controllers that need to interact with several repositories. Eventually, your code will become a rat's nest of service config and injection boilerplate. However, at that point, you should really be employing the unit of work pattern as well, encapsulating all your repositories in one class that you can inject instead. But wait, oh yeah, that's what DbContext is already. It's a unit of work encapsulating multiple repositories, or DbSets. This is why you shouldn't being using the repository pattern in conjunction with Entity Framework. It's a pointless abstraction that does nothing but add additional and unnecessary entropy to your code.
If you want to abstract DbContext, then you should use something like the service layer pattern (not to be confused with the RPC bull excrement Microsoft refers to as the "service pattern") or the CQRS (Command Query Responsibility Segregation) pattern. The repository pattern is for one thing: abstracting away raw SQL. If you don't have raw SQL, you should not be implementing that pattern.

Ninject factory management

I'm using Ninject.Extensions.Factory to control the lifecycle of the repository layer. I want to have a single point of reference from which I can get a reference to all repositories and have them lazily available. Ninject Factory approach seems like a good solution but I'm not too sure about my solution:
public class PublicUow : IPublicUow
{
private readonly IPublicRepositoriesFactory _publicRepositoriesFactory;
public PublicUow(IPublicRepositoriesFactory publicRepositoriesFactory)
{
_publicRepositoriesFactory = publicRepositoriesFactory;
}
public IContentRepository ContentRepository { get { return _publicRepositoriesFactory.ContentRepository; } }
public ICategoryRepository CategoryRepository { get { return publicRepositoriesFactory.CategoryRepository; } }
}
The problem lies in the PublicRepositories class.
public class PublicRepositoriesFactory : IPublicRepositoriesFactory
{
private readonly IContentRepositoryFactory _contentRepositoryFactory;
private readonly ICategoryRepositoryFactory _categoryRepositoryFactory;
public PublicRepositoriesFactory(IContentRepositoryFactory contentRepositoryFactory, ICategoryRepositoryFactory categoryRepositoryFactory)
{
_contentRepositoryFactory = contentRepositoryFactory;
_categoryRepositoryFactory = categoryRepositoryFactory;
}
public IContentRepository ContentRepository { get { return _contentRepositoryFactory.CreateContentRepository(); } }
public ICategoryRepository CategoryRepository { get { return _categoryRepositoryFactory.CreateCategoryRepository(); } }
}
I'm worried that this will become hard to manage as the number of repositories increases, this class might at some point need to have around 20-30 constructor arguments with the current implementation.
Is there an approach I can take to reduce the number of ctr arguments, like passing an array/dictionary of interfaces or something similar?
I've thought about using property injection in this scenario but most articles suggest avoiding property injection in general.
Is there maybe a more general pattern that would make this easier to manage?
Is this in general a good approach?
It has become rather common practice to use a repository interface like
public interface IRepository
{
T LoadById<T>(Guid id);
void Save<T>(T entity);
....
}
instead of a plethora of specific repositories like IContentRepository, ICategoryRepository,..
specific repositories are only ever useful in case of having specific logic to the entity type and an operation, for example verifying that it's valid. But such operations are rather an "aspect" or a cut-through-concern which you should model as such. Managing/doing validation on save should not be implemented x-times but only once. The only thing you should specifically implement are the exact validation rules (DRY). But these should be implemented in separate classes and used by composition, not inheritance.
Also, for stuff like retrieving an entity or multiple entities "based on a use case", you should use specific query classes, and not put methods on a repository interface (SRP, SOC). An example would be GetProductsByOrder(Guid orderId). This should be neither on the Products nor the Order Repository but rather in a separate class itself.
Taking things a step further, it does not seem a good idea to use a factory to late create all repositories. Why?
makes software more complex (thus harder to maintain and extend)
usually negligible performance gain
deteriorates testability
also see Mark Seeman's blog post Service Locator is an anti pattern, where he's also talking about the disadvantages of late-creation vs. the composition of the entire object graph in one go.
I'm not trying to say that you should never use factory/lazy, but only when you've got a really good reason to :)
Example of a query
I'm not very familiar with EntityFramework. I know NHibernate a whole lot better, so behold.
public class GetParentCategoriesQuery : IGetParentCategoriesQuery
{
private readonly EntityFrameworkContext context;
public GetParentCategories(EntityFrameworkContext context)
{
this.context = context;
}
public IEnumerable<Category> GetParents(Category child)
{
return this.context.Categories.Where(x => x.Children.Contains(child));
}
}
So basically the only thing you change is extracting the GetParentCategoriesQuery into it's own class. The DbContext instance must be shared with the other query and repository instances. For web projects, this is done by binding the DbContext .InRequestScope(). For other applications you may need to use another machanism.
The usage of the query would be quite simple:
public class CategoryController
{
private readonly IRepository repository;
private readonly IGetParentCategoriesQuery getParentCategoriesQuery;
public CategoryController(
IRepository repository,
IGetParentCategoriesQuery getParentCategoriesQuery)
{
this.repository = repository;
this.getParentCategoriesQuery = getParentCategoriesQuery;
}
public void Process(Guid categoryId)
{
Category category = this.repository.LoadById(categoryId);
IEnumerable<Category> parentCategories =
this.getParentCategoriesQuery(category);
// so some stuff...
}
}
An alternative to the scoping is to have the repository instantiate the the query type and pass the DbContext to the query instance (this can be done using the factory extensions):
public TQuery CreateQuery<TQuery>()
{
return this.queryFactory.Create<TQuery>(this.context);
}
which would be used like:
IEnumerable<Category> parents = repository
.CreateQuery<GetParentCategoriesQuery>()
.GetParents(someCategory);
But please note that this alternative will again only late-create the query and thus result in less testability (binding issues may be remain undetected for longer).
The GetParentCategoriesQuery is part of the repository layer, but not part of the repository class.

How can I inject the Repositories to the UnitOfWork?

I've implemented my UnitOfWork so that it keeps references to all repositories.
public interface IUnitOfWork
{
void Commit();
void RollBack();
}
public interface IMyUnitOfWork : IUnitOfWork
{
IFooRepository Foos { get; }
IBarRepository Bars { get; }
// Other repositories ...
}
Note that the repositories implements a generic type of repository interface.
public interface IFooRepository : IRepository<Entities.Foo>
{
// FooRepository specific methods goes here.
}
public interface IRepository<T> : IRepository
where T : class
{
}
Now how can I inject these repository to my UnitOfWork. Of course I want them with a lazy loading behavior. For example:
public class ConcreteUnitOfWork : IMyUnitOfWork
{
private readonly IUnityContainer unityContainer;
private IFooRepository fooRepository;
public ConcreteUnitOfWork(IUnityContainer unityContainer)
{
this.repositoryFactory = repositoryFactory;
}
public IFooRepository Foos
{
get
{
return this.fooRepository ??
(this.fooRepository = unityContainer.Resolve<IFooRepository>());
}
}
}
I know passing the Unity container to the UnitOfWork is incorrect but what pattern would you offer to solve this issue?
You may mention that I shouldn't keep the repository references in the UnitOfWork but please suppose a service class which needs several repositories. With this design I can just pass the UnitOfWork as the constructor parameter (Constructor Injection) to the service class, but if I didn't keep the repository references in UnitOfWork, I would have to pass all needed repositories as constructor parameters and you know what it leads to.
-- UPDATE --
Please let me know if I'm absolutely wrong and I should never compose the repositories in UnitOfWork. Then please give me a solution about "Constructor Over-injection" here.
-- UPDATE2 --
It seems that composing (referencing to) the repositories from UnitOfWork breaks the Open/Closed principle as we need to change the UnitOfWork class when we add a new repository (add a new property).
If it's right then I should consider a refactoring. Would you please give me some ideas?
It seems as though the current design proposal mixes more than one responsibility into the IMyUnitOfWork interface. You say that this is because otherwise a service class might need to take each Repository independently. I'm assuming you mean something like this:
public MyService(
IUnitOfWork uow,
IFooRepository fooRepository,
IBarRepository barRepository)
This seems to me to be a much simpler and cleaner design.
But then what about Constructor Over-injection?
Well, there's that... but the thing is that this is exactly the same problem you now have with your ConcreteUnitOfWork implementation. You haven't solved the Constructor Over-injection smell at all - you've just moved it to another class.
Actually, by moving it to ConcreteUnitOfWork you've made it more difficult to deal with the situation. Because ConcreteUnitOfWork is a pure infrastructure class (or a support class, if you will) it doesn't have any business context, so it's really hard to suggest a way resolve the Constructor Over-injection smell here.
On the other hand, a given Service (or perhaps a Controller) would tend to be more specialized and have knowledge of the business context, so it wouldn't need every repository in order to do its job - or if it does, it probably attempts to do too much.
Such a specific business component can better be refactored to a Facade Service.

Repository Pattern pros and cons of each implementation

Hi looking at the repository pattern which commonly seems to be implemented something like:
public class GenericRepository<TEntity> where TEntity : class
{
// other business
public virtual TEntity GetByID(object id)
{
return db.Set().Find(id);
}
public virtual void Insert(TEntity entity)
{
db.Set().Add(entity);
}
public virtual void Delete(object id)
{
TEntity entityToDelete = db.Set().Find(id);
Delete(entityToDelete);
}
public virtual void Update(TEntity entityToUpdate)
{
db.Set().Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
So for every type you want to work with (ie update) you need to instantiate a repository.
So if I had two types I wanted to save Cars and Trucks I would need to go:
var carRepository = new GernericRepository<Car>();
carRepository.Update(myCar);
var truckRepository = new GernericRepository<Truck>();
carRepository.Update(myTruck);
So then you have seperate repositories for each type. To make sure you save everything at once you need the unitOfWork to ensure they all use the same context and save at one time.
Surely wouldn't it be better to have something like:
public class GenericRepository
{
// other business
public virtual TEntity GetByID<TEntity>(object id) where TEntity : class
{
return db.Set<TEntity>().Find(id);
}
public virtual void Insert<TEntity>(TEntity entity) where TEntity : class
{
db.Set<TEntity>().Add(entity);
}
public virtual void Delete<TEntity>(object id) where TEntity : class
{
TEntity entityToDelete = db.Set<TEntity>().Find(id);
Delete(entityToDelete);
}
public virtual void Update<TEntity>(TEntity entityToUpdate) where TEntity : class
{
db.Set<TEntity>().Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
This means the repository only needs to be instantiated once and therefore is truely generic?
So you could update your cars and trucks like this:
var repository = new GernericRepository<Car>();
repository.Update<Car>(myCar);
rRepository.Update<Truck>(myTruck);
Surely this is a better method? Am I missing something? It automatically has only one context too.
The repository pattern does not decouple the data access from the data store, that is what the ETL tool such as NHibernate or the Enity Framework does for. The repository pattern provides reusable methods for extracting data.
I have previously used a so called "Generic" repository as you have described and thought it was great. It isn't until you realise that you have just put another layer on top of NHibernate or the Entity Framework you realise it's all gone Pete Tong.
Ideally what you want are interfaces that describe ways of getting data out of your data store and should not leak what data access you are using. For example:
public interface IEmployee
{
IEmployee GetEmployeeById(Guid employeeId);
IEmployee GetEmployeeByEmployeeNumber(string employeeNumber);
IEnumerable<IEmployee> GetAllEmployeesWithSurname(string surname);
IEnumerable<IEmployee> GetAllEmployeesWithStartDateBetween(DateTime beginDateTime, DateTime endDateTime);
}
This gives you a contract to code to, there is no knowledge of your persistence layer and the queries used to retrieve the data can be unit tested in isolation. The interface could inherit from a base interface that provides common CRUD methods but you would be assuming that all your repositories would need CRUD.
If you go down the road of a Generic Repository you will end up with duplication in your queries and you will find it much harder to unit test the code that uses the repository as you will have to test the queries as well.
Generics by itself does not make an implementation of the repository pattern. We've all seen the generic base class used in example repository pattern implementations but this is to make things DRY (Don't-Repeat-Yourself) by inheriting from the base class ( GenericRepository in your case) to more specialized child classes.
Only using the generic, base class GenericRepository assumes that your repositories will only ever need the most basic CRUD methods. For a more complex system, each repository becomes more specialized based on underlying business entities data requirements.
Also, you will need to have interfaces that define your data contracts with your other layers. Using the repository pattern means you don't want to expose your concrete implementations of your repositories to your other layers.

Appropriate Repository LifeCycle Scope w/ Ninject in MVC

What is the appropriate LifeCycle Scope for a repository and the EF context when using Entity Framework 4 with Ninject in an MVC 3 application?
I've been using the default of InTransientScope, but questioning whether it should be InRequestScope.
public class MyController: Controller
{
private readonly IMyRepo _repo;
public MyController(IMyRepo repo)
{
_repo = repo;
}
public ActionResult Index()
{
var results = _repo.GetStuff();
return View(results);
}
}
Ninject Module:
public class MyServices : NinjectModule
{
public overrride void Load()
{
Bind<IMyRepo>.To<MyRepo>();
Bind<MyContext>.ToSelf();
}
}
MyRepo:
public class MyRepo: IMyRepo
{
private readonly MyContext _context;
public MyRepo(MyContext context)
{
_context = context;
}
public IEnumerable GetStuff()
{
return _context.Entity;//query stuff
}
}
Your repository can be transient scope, however, I would bind the context in request scope. This way all of your repository instances will share the same context. This way you can reap the caching and transactional benefits of an ORM.
The way it works currently in your code is that a new context is created any time you request one. So if your controller first uses a repository and then calls another module that in turn uses a repository. Each of those repositories will have a different instance of the context. So in effect you are now using your ORM simply as a connection manager and SQL generator.
This can also have unintended consequences. Imagine a code like the following:
public ActionResult MyAction(int id)
{
var entity = _repository.Get<Entity>(id);
entity.Prop = "Processing";
_module.DoStuff(id);
}
If the DoStuff method, eventually calls _repository.Get<Entity>(id); again, you will have 2 different copies of your entity that are out of sync.
This depends on a couple of factors.
Do you care about transactions at all? It not that transient scope is ok for you.
Do you care about transactions but think one transaction per web request is ok for you? Then use web scoped.
Are you ok with objects being "cached" in EF's context and don't want a full database refresh if you request the same object twice? Web scope has this side effect.

Resources