What I have learned by building .NET Stars -part 4- Keyed Dependency Injection – constructor by keys
As I said before, I have constructed first the interfaces. Then I have a null object pattern for each interface, constructed automatically with a Roslyn Code Generator , https://www.nuget.org/packages/rscg_Interface_to_null_object .
And now, what I want is to have keyed DI for each new implementation -with a twist: It’s like a game of matching keys when another class is injected, the first one gets chosen if it has the exact same key!
Let me give an illustrative example :
Imagine interfaces IA and IB, with Class_A_Null and Class_B_Null as their null object counterparts. These are injected by default into our DI container
We have class class_A_Data1 that implements IA.
It is injected with key “Data1”
We have class B_Data1 ( implements IB ) that has a constructor that has a parameter IA .
It is injected with key “Data1”
We have class B_Data2 ( implements IB ) that has a constructor that has a parameter IA .
It is injected with key “Data2”
So every time we construct an IB it requires it’s companion , IA .
Now let’s say I want DI to construct B_Data1 and B_Data2
When want to construct B_Data1 , it sees that has a Key “Data1” . See that he needs also an IA –
DI can choose between default implementation “Class_A_Null” ( without key ) and “class_A_Data1” with the key “Data1”
Because it has the same key (“Data1” ) as the class that must be implemented (“B_Data1” ) chooses class_A_Data1
When want to construct B_Data2 , it sees that has a Key “Data2” . See that he needs also an IA.
DI can choose between default implementation “Class_A_Null” ( without key ) and “class_A_Data1” with the key “Data1”
Because the class to be constructed has the key “Data2”, the “class_A_Data1” with the key “Data1” is eliminated.
So it constructs B_Data2 with the default implementation , “Class_A_Null” ( without key )
Why this constraint ? Because I started with null implementation, and add one by one the implementation.
The WebAPI works every time ( the null implementation does nothing , so it works ).
And slowly but surely we add to the DI key another implementation and we are sure that works every time .
This innovative use of keyed dependency injection, particularly starting with null object patterns, allows for iterative development without breaking existing functionalities. As each new implementation is added, the system remains stable and functional, gradually enhancing its capabilities with each iteration.
Feel free to experiment with these ideas and adapt them to your own projects. Start by trying out the rscg_Interface_to_null_object package, and see how it can transform your development workflow
You can see at https://ignatandrei.github.io/dotnetstats/ and the source code at http://github.com/ignatandrei/dotnetstats/
The code for this special DI is at https://github.com/ignatandrei/dotnetstats/blob/main/src/Stats/StatsConsole/KeyedServiceCollection.cs ( too long to put here )
Leave a Reply