- 1. Inversion of Control
- 2. Why dependency injection?
- 3. C# ServiceCollection and ServiceProviders class
- Inversion of Control (IoC).
- The approach of outsourcing the construction and management of objects.
- App should be configurable.
- Easily change the payment for another type.
- Pix, Credit Card, Debit Card...
- Primary functions:
- Create and manage objects (Inversion of Control).
- Inject object dependencies (Dependency Injection).
- The dependency injection mainly comes from an object oriented design principle, concrete classes must not be dependent on each other, this is called low coupling.
- Then we say that they are highly coupled and opposite when they are not depending on each other.
C# Example with highly coupled
- The problem is that imagine that this
DataAccessclass rights, the data to SQL Server, and you have, for example, 10 lines of code that divides the data to SQL Server. If we want to switch from SQL Server to, for example, MySql or to a NoSql database, either you have to come and change the body of your method, which this is against the openclosed principle, because what if we want to go back to SQL Server at some point, you have to again come back and put your old code back in here, or how about the tests that you might have lacunae test and integration test. - You break all your tests so your
Businessclass now has dependency on yourDataAccessclass, because if I change the data access, I'm going to break theBusinessclass. - Your new
DataAccessnecessarily won't have the same method store or even if they have the same methods, then the signature might be different. - Likewise, your
UserInterfaceclass has dependency on yourBusinessclass. - Again, if you want to change the way we validate data, we will have to change the body of the business class and that can again break a lot of parts of your application.
- To reduce this type of coupling or dependency, what we can do is that your user interface can work with an
interfaces. - So instead of working directly with the
Businessclass, which is the concrete class, it can work with an interface because the interface has the method and has the parameters for the method. - Your
UserInterfacecan use the interface. - It can only talk to the interface because what your
UserInterfaceneeds is that what methods exist in theBusinessclass and what is the signature of that method. - Likewise, your
DataAccessdoesn't have to be there as long as there is an interface that has the methods and method signatures and possibly the properties that the business class needs in order to talk to theDataAccesslayer orDataAccessclass, theBusinessclass will be fine so we can replace theBusinessclass with an interface that demonstrates the methods, properties and method signatures of theBusinessclass. - Likewise, we can replace the
DataAccessclass with an interface that represents the methods, properties and method signatures of the data access class. SoUserInterfacewill work with theIBusinessclasses interface andBusinessclass will work with theIDataAccessinterface. - And now every time we want to actually do something in the
Businessclass, dependency injection comes into play and creates an instance of theBusinessclass and then makes a call to the actual methods inside theBusinessclass. - Likewise, whenever we need an actual
DataAccess, then dependency injection creates an instance of yourDataAccessclass, which implements theIDataAccessinterface orDataAccessclass, and performs the actual writing or storing data in your database.
C# Example reducing coupling with interfaces
- Clean code
- Your code is easier to understand
- So when you use dependency injection, your code will be a lot cleaner and easier to understand, because, for example, if I only use a
Businessclass orIBusinessinterface and not the actual concrete classes, all you need to know is that what is the signature, what are the methods and what are the properties.
- So when you use dependency injection, your code will be a lot cleaner and easier to understand, because, for example, if I only use a
- Your code is easier to understand
- Better reusability
- Low coupling allows modules to be reused
- You don't need to know the details of how things work in a
Businessclass. So it will be easier to understand a given code and then the modules and classes will be more usable because you know the interfaces of the classes. If the classes implement a given interface, then you can easily reuse them anywhere that interface is known.
- You don't need to know the details of how things work in a
- Low coupling allows modules to be reused
- Better unit testing
- Concrete class can be replace by mocks
- And also dependency, injection and interfaces make unit testing very easy. In fact, interfaces and dependency injection is crucial for writing good unit tests because in unit tests you only test one module and all the other dependencies should be just fake or mock's, which mean that they shouldn't actually do anything.
- Concrete class can be replace by mocks
- Low coupling
- Concrete classes can be replaced
- You can easily replace concrete classes because if you use the interface, you don't really need to know how actual concrete classes work and that will help you with low coupling.
- Concrete classes can be replaced
- In independence injection, there is a
bucketorcontainerwhich we put all themetadatainside it. - For example, imagine that in the
bucket, your metadata is thatILoogerhas to be translated to a class calledLoggerbecause independents injection, we rely on interfaces in order to reduce the coupling and reduce the dependency instead of putting classes and objects in themetadatabucket. - We normally say every time you see an interface called
ILogger, what I want is an object of type defaultLogger. - So we put all the
metadatain abucketand thatbucket, which is our dependency injection container, is represented indotnet corewith a class calledServiceCollection.- So a
ServiceCollection, which implements an interface calledIServiceCollection, that is your dependency injection container and it includes yourmetadata. - It doesn't include your actual data.
- It's only
metadatathat sits in thebucketand yourmetadatabegins with your interface. - A
ServiceCollectionis only responsible for including and containing themetadata.- It doesn't create the actual C# or dotnet core objects.
- So a
ServiceProviderwhich implements an interface calledIServiceProvideris responsible to create instances of objects and pass them to you.- The
ServiceCollectionin order to put our metadata in it, and thenServiceCollectionwill give us an instance ofServiceProviderand then we always askServiceProviderto give us the objects that we need.
- ServiceCollection
- So the responsibility of
ServiceCollectionis holding the metadata and mapping of types.
- So the responsibility of
- ServiceProvider
- The responsibility of
ServiceProvideris creating instances and managing the lifetime of the instances.
- The responsibility of
creating instances and managing the lifetime of the instances.
- Same instance for the entire application
- Same instance for the whole request
- Different instance every time object is requested or injected
- In this scenario whats the best options?
public class ClassWithStaticProperty
{
public static List<int> PrimaryKeys;
public void Save()
{
}
}
- AddScoped or AddTransient?
- And there is and is that the
PrimaryKeysproperty is a static static properties are not dependent on the instance. - There is only one instance of this property and that is across the whole application because it is a static.
- So no matter whether you use AddTransient or AddScoped, you will always have only one object
PrimaryKeys.
- And there is and is that the



