I am starting to work with DI/IoC and I have some troubles understanding all the concepts.
I have chosen Autofac because it seems it's one of the few that supports both .Net 4.6+ and .Net Core. It seems it also most widely used.
1) Constructor injection - for e.g. in Controllers or my WCF services
I understand that it is impossible to do constructor injection to an object that I am instantiating in my code, meaning it is not automatically instantiated.
2) Property injection
I would like to do something similar to how you do it in Ninject:
[Inject]
public IWeapon Weapon { get; set; }
And as I understund, in Autofac. it is equivelanet to:
builder.RegisterType<Weapon>().As<IWeapon>().PropertiesAutowired();
1. Now, why is the constructor injection the preferred way?
For example, I have:
Factory for repositories
Factory for business engines
Those factories, are just one-liners that should do something like (from another IoC):
public class DataRepositoryFactory : IDataRepositoryFactory
{
T IDataRepositoryFactory.GetDataRepository<T>()
{
return ObjectBase.Container.GetExportedValue<T>();
}
}
Some methods require both, some do not. Doing something like:
public SampleControllerOrManager(IUnitOfWork unitOfWork, IRepositoryFactory repositoryFactory, IBusinessEngineFactory engineFactory)
seems like a waste of resources.
I understand that this helps with testing (?).
But this looks cleaner:
public SampleControllerOrManager(IUnitOfWork unitOfWork)
[Inject]
public IRepositoryFactory RepositoryFactory { get; set; }
[Inject]
public IBusinessEngineFactory EngineFactory { get; set; }
2. Injecting Entity Framework DbContext into the repositories
I want to register the context with the Container and have that injected into the object constructors of the UnitOfWork and the Repository's. I want to be sure the same instance is injected into all the objects. How do I do it in Autofac?
public class Repository : IRepository {
//context injected here
public Repository (DbContext context){ ... }
}
public class Manager {
public void SomeMethod(){
IRepository = RepositoryFactoryGetDataRepository<ISomeTypeRepository>
}
}
Constructor Injection
Constructor injection is the preferred way because it makes them obvious. You can't instantiate the class if you do not provide the required dependencies.
With property injection dependencies are hidden and you could instantiate the class with some missing injections which could lead you to believe that the class is fully initialized and ready to be used. Eventually, you could get an error if you try use a functionality that needs a missing dependency.
Instance Scope
To be sure that the same instance is injected, you could register your DbContext as Singleton.
For example:
var builder = new ContainerBuilder();
builder.RegisterType<DbContext>().SingleInstance();
Or, depending on your needs, you could register it using the Instance Per Request scope:
var builder = new ContainerBuilder();
builder.RegisterType<DbContext>().InstancePerRequest();
Note: You may find this article written by Martin Fowler useful.
Related
I would like to prevent other developers from deviating from the application's architecture by limiting the classes in which the UnitOfWork class can be injected. Or at least make it more obvious that they're deviating from the accepted pattern.
We have a collection of services that all extend the abstract class of BaseService. The BaseService class contains the property for the UnitOfWork class which is injected via dependency injection.
public abstract class BaseService
{
protected readonly IUnitOfWork UnitOfWork;
protected BaseService(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
}
This means if a class needs the UnitOfWork it'll need to extend the BaseService class, but nothing actually prevents a developer from just injecting the UnitOfWork into some other class that's not a service. If they did this, they could potentially be saving changes outside of the service, which is what we're trying to avoid.
Is there a way that we can throw a build error or warning based on the UnitOfWork being injected in some other class?
Two possible solutions come into my mind: One is based on using DI framework features to make the registration only visible in a specific scope of the code. The other one is based on using a public and an internal interface, while the implementation is only registered for the internal interface.
Solution based on DI framework
I best know Autofac, so I name the solution for this DI framework here. But I think other DI frameworks have similar features, so a bit of searching could give you the corresponding feature in your DI framework:
In case that your dependency injection framework is Autofac you can work with lifetime scopes to make specific registrations only available in a limited "area" (scope) of your code. (See also at the official Autofac documentation for an explaination about the concept of liftime scopes: https://autofac.readthedocs.io/en/latest/lifetime/index.html)
Solution via splitting the interface
This approach is to split IUnitOfWork into two interfaces - one which is public and one which is internal and therefore not accessible from other projects. The implementation is only registered for the internal interface, so that other projects cannot inject anything, as the interface is not known to them.
public interface IUnitOfWork
{
// ...
}
internal interface IInjectableUnitOfWork : IUnitOfWork
{
// no content
}
public abstract class BaseService
{
protected readonly IUnitOfWork UnitOfWork;
protected BaseService(IInjectableUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork; // hint: The assignment works, because IInjectableUnitOfWork inherits from IUnitOfWork.
}
}
In my current project my manager is forcing some design concept for dependency injection I would like to discuss because I’m curious what a specialists of dependency injection think about this approach. The ideas behind this is use of class called catalog that is implemented per each service (service in Service Fabric) and having all dependencies inside like this:
public interface IDepA
{
}
public interface IDepB
{
}
public interface IDepC
{
}
public class StandardConstructorInjectorService
{
private readonly IDepA _depA;
private readonly IDepB _depB;
private readonly IDepC _depC;
public StandardConstructorInjectorService(IDepA depA, IDepB depB, IDepC depC)
{
_depA = depA;
_depB = depB;
_depC = depC;
}
}
public class ServiceCatalog
{
private readonly Container _container;
public ServiceCatalog(Container container)
{
_container = container;
}
public IDepA DepA => _container.GetInstance<IDepA>();
public IDepB DepB => _container.GetInstance<IDepB>();
public IDepC DepC => _container.GetInstance<IDepC>();
}
public class ServiceWithCatalog
{
private readonly ServiceCatalog _catalog;
public ServiceWithCatalog(ServiceCatalog catalog)
{
_catalog = catalog;
}
}
From my perspective we have
Pros:
Code that is using catalog is simple
Dependencies can be used in Lazy mode so when code logic is not using them they will not be created – but on other hand I know that we should design classes in such way that they will use all dependencies
It is easy bootstrap those classes because they have one predefined catalog
Cons:
Dependencies to class is not directly visible
Smell for service locator but we use resolve only in catalog definition and not in business code so I’m not sure is this acceptable or maybe dependency injection police will hunt us down :)
What do you think about this approach?
Your ServiceCatalog class depends on the Container. This effectively makes this a Service Locator, which is an anti-pattern. The fact this this class is not 'business code' is irrelevant. The only thing that matters is that it is not part of the Composition Root, which makes this an anti-pattern.
Besides using an anti-pattern, the class exposes its dependencies, rather than hiding them, which is a bad idea as well. The main idea of this class is probably to group commonly used dependencies together, lowering the number of constructor dependencies a class has. Problem with this, however, is that it doesn't lower the complexity of a consuming class, but simply obscures the fact that a class has too many dependencies. A class with too many dependencies likely violates the Single Responsibility Principle.
Instead of using this service catalog 'pattern', stick to using Constructor Injection. When a class gets too many constructor dependencies, a code-smell called Constructor Over-Injection, action should be taken. There are many solutions for this, such as Facade Services, Decorators or Domain Events. A Facade Service hides its dependencies rather than exposing them.
All this information, and much more, can be read in this book, by Mark Seemann and myself.
Please help me out, how should I pass DBContext object to the constructor of MyEntityRepsitory class?
For example:
public interface IRepository<T> where T: class
{
}
public class Repository<T> : IRepository<T> where T : class
{
private readonly DbContext _dbContext;
public Repository(DbContext dbContext)
{
_dbContext = dbContext;
}
}
public interface IMyEntity : IRepository<MyEntity>
{
MyEntity GetSingle(int Id);
}
public class MyEntityRepository : Repository<MyEntity>, IMyEntity
{
public MyEntityRepository() : base(mydbContext){}
}
I am new to design patterns and implementing repository pattern for my data access layer. I never used Structure map / Unit of Work pattern.
I want to know, how many ways I can create DbContext object so that I can pass.
And please explain me the difference of various approaches.
In the above example class named MyEntityRepository has a constructor and which passes dbContext object to the Repository class constructor. Please tell me how to do that.
Many thanks.
Edit
As per #Trevor de Koekoek's comment, direct injection of a wrapper owning a DbContext can be problematic from a threading and transaction boundary point of view.
In hindsight, injection of a factory is preferable, and used like so:
public ConsumingClass(IRepositoryFactory injectedRepositoryFactory)
And then (if holding the reference to the factory)
using (var applesRepository = _injectedRepositoryFactory.CreateRepository<Apples>())
{
... do something with apples
}
or by implementing IDisposable on the class.
This gives the client a clean repository, and forces the client to take ownership of the repository instance.
Original Answer
As you've suggested, you should configure an IoC container (like StructureMap) to do this for you - classes which need to use an IRepository<T> will have an instance injected via either constructor or setter injection. This IMO is the cleanest implementation, as it has testability, the coupling to Repository is via Interface only, and neither Repository nor consuming classes are coupled to the IoC container.
e.g. using Constructor injection:
public class ConsumingClass
{
public ConsumingClass(IRepository<Apples> injectedApplesRepository)
}
The mapping of IRepository to its concrete class is done via the IoC Bootstrapper (or in config). For improved testability, I would also couple your repository to IDbContext, not to DbContext, e.g.
private void ConfigureIoC()
{
For<IDbContext>().Use<MyDbContext>();
For<IRepository<T>>().Use<Repository<T>>();
// ... etc
}
When your consuming class is built up by the IoC, it will recursively detect all dependencies (IRepository<T>, and then in turn IDbContext) and built these up, and their depedencies etc.
The other alternatives are patterns like Service Locator Pattern (now often regarded as an anti pattern, as it couples classes to the locator), and Factory Method.
I'm trying to implement a Generic Repository. This is what I've got so far ...
public interface IRepositoryFactory
{
IRepository<T> RepositoryOf<T>() where T : class;
}
public class EntityFrameworkRepositoryFactory : IRepositoryFactory
{
private readonly IWindsorContainer _container;
public EntityFrameworkRepositoryFactory(IWindsorContainer container)
{
_container = container;
}
public IRepository<T> RepositoryOf<T>() where T : class
{
var repository = _container.Resolve<IRepository<T>>();
return repository;
}
}
The RepositoryFactory is used by my unit of work implementation
public interface IUnitOfWork : IDisposable
{
IRepository<T> RepositoryOf<T>() where T : class;
void Commit();
}
Anyway, the question I want to ask is whether having the RepositoryFactory implementation depend on IWindsorContainer is correct?
I needed a way of asking for an IRepository of any type, so my installer code does this ...
// Windsor Container
container.Register(
Component.For<IWindsorContainer>()
.Named("Container")
.Instance(container)
);
Which just seems to go against the whole concept of IoC, but then maybe the whole idea of asking for a repository does that anyway.
Edit (As reply to miensol's answer)
I am already using Windsor to create the repositories for me with the following code in my installer ...
// Generic Repository
container.Register(
Component.For(typeof (IRepository<>))
.ImplementedBy(typeof (EntityFrameworkRepository<>))
.ServiceOverrides(
ServiceOverride.ForKey("objectContext").Eq("ObjectContext"))
);
I have used ServiceLocator in the past to achieve what I want, but have read that it's a bit of an anti-pattern. So was trying to avoid using it. Although I have to admit that I'm not sure why, as what I've done also seems wrong as I am bound to using Castle Windsor as my IoC/DI framework. Service Locator is meant to be framework agnostic.
So, I'm a bit confused!
I'm not entirely sure why do you need IRepositoryFactory when you are using an IoC framework. However having dependencies to specific IoC container implementations scattered though the code base is generally not a good idea. Most of the time when I really can't find a way to make the container inject dependencies to my objects I use Service Locator Pattern, here you can find a commonly used implementation for .net. Then your factory method would look like this:
public IRepository<T> RepositoryOf<T>() where T : class
{
return ServiceLocator.Current.GetInstance<IRepository<T>>();
}
Nevertheless it seems like you could just make Windsor create the generic repository for you anyways:
container.Register(
Component.For(typeof(IRepository<>)).ImplementedBy(typeof(GenericRepositoryImplementation<>))
);
and having them injected to your objects like so:
public class ClassThatRequiresSomeRepos
{
IRepository<OneEntity> repoOne;
IRepository<TwoEntity> repoTwo;
public ClassThatRequiresSomeRepos(IRepository<OneEntity> oneEntityRepository, IRepository<TwoEntity> twoEntityRepository)
{
_repoOne = oneEntityRepository;
_repoTwo = twoEntityRepository;
}
}
So I'm starting to use Ninject for dependency injection and I'm wondering what people think of using a kernel as an object factory for Unit of Work type objects like Linq2Sql Datacontexts. I would just inject them like normal dependencies, but this introduces some object lifetime issues I'd like to avoid. DataContexts are different than general dependencies because you're supposed to spin up new instances as needed and dispose of them when you're done.
To do something like this I'd simply setup a provider like so...
class SomeDataContextProvider : Provider<SomeDataContext>
{
private static string _connectionString = "someConnectionString"
protected override SomeDataContext CreateInstance(IContext context)
{
return new SomeDataContext(_connectionString);
}
}
Bind them in a module...
class MyModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<SomeDataContext>().ToProvider(SomeDataContextProvider);
}
}
And use the standard kernel when needed...
class MyClassThatNeedsADataContext
{
private StandardKernel _kernel = new StandardKernel(new MyModule());
public void SomeMethod()
{
using (var db = _kernel.Get<SomeDataContext>())
{
//Use the context
}
}
}
It seems a little heavy for what is essentially a static factory but I'm using Ninject for other stuff anyway. I like that it gives members on the team a convention for factories instead of just letting them wing it (creating a bunch of different factory classes in weird places, or just putting static methods on the objects etc).
Thoughts? Is there a better way to deal with Unit of work dependencies like DataContexts or WCF Service Clients using dependency injection?
I don't like injecting containers into classes since it creates a dependency between your application and the container, and makes it less clear what dependencies a class has. I don't really see how this approach gains you anything over a factory, so personally I'd create a 'DataContextFactory' and inject that into any classes that need to access the database.