Тёмный

Dependency Injection Is Now Complete In .NET 8! 

Nick Chapsas
Подписаться 302 тыс.
Просмотров 93 тыс.
50% 1

Use code ARCH15 and get 15% off the brand new Solution Architecture course on Dometrain: dometrain.com/...
Become a Patreon and get source code access: / nickchapsas
Hello, everybody, I'm Nick, and in this video, I will show you a brand new feature that was added in .NET 8 for Dependency Injection that many people, including myself, were missing.
Workshops: bit.ly/nickwor...
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: bit.ly/ChapsasG...
Follow me on Twitter: bit.ly/ChapsasT...
Connect on LinkedIn: bit.ly/ChapsasL...
Keep coding merch: keepcoding.shop
#csharp #dotnet

Опубликовано:

 

8 сен 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 268   
@veljkozrnic3897
@veljkozrnic3897 Год назад
The use case that's actually useful for this is providing multiple versions of your API. You decorate your services worth attributes that specify versions, you inject specific version based on the requested API version that was invoked.
@Chris-ud8bi
@Chris-ud8bi Год назад
Underrated comment
@RandallEike
@RandallEike Год назад
Regarding naming the keys for injection, they should be named for their purpose, not for their implementation. Instead of "openweathermap" and "weatherapi" they should be "main" and "backup". That is the point of injecting interfaces as in the future you may decide to prefer weatherapi as you main service for example.
@Psykorr
@Psykorr Год назад
Ok not really the piont of the video I guess but maybe it is a correct statement any way I think
@robslaney3729
@robslaney3729 Год назад
You also now have to know which one you want at compile time. Can't switch to backup without recompiling.
@Rider0fBuffalo
@Rider0fBuffalo Год назад
This makes sense to me, because using names of service implementation itself is pointless because you might as well just register, and resolve the service by class instead of by interface.
@gregorymeadows3572
@gregorymeadows3572 Год назад
@@robslaney3729 He didn't show it here as its implied, but you would conditionally choose which one to use where based on whatever logic your business needs, feature flags or whatever. (If X request fails, call Y instead)
@MikeMcGranahan
@MikeMcGranahan Год назад
The author makes this point at the end of the video. Would've been better to demonstrate it in the example code.
@mrwensveen
@mrwensveen Год назад
This feels suspiciously like the service locator antipattern. Also, it breaks separation of concerns somewhat, unless your concern is the fallback mechanism specifically. I'd create an IWeatherService implementation, FallbackWeatherService, or something, which would take two (or a list of) IWeatherServices and register that in the DI container.
@robl39
@robl39 Год назад
100% agree service locator makes me vomit!
@MikeMcGranahan
@MikeMcGranahan Год назад
The keys used in the code example do reflect bad practice. But the discussion at the end about "throttled"/"unthrottled", "internal"/"external", "cached"/"uncached" are valid use cases where this feature can be used in a Good™ way.
@dirkp.6181
@dirkp.6181 11 месяцев назад
​@@MikeMcGranahan But still, those are technical concerns and must by no means litter business code.
@RandallEike
@RandallEike Год назад
This demonstrates how to get both the main and backup services for retrieving weather. But what I thought you were going to show is how to gracefully degrade to the backup when the main service is down; that is the more interesting problem here.
@RandallEike
@RandallEike Год назад
@@jkdmyrs yes, I realize you could simply try and fall back there, but that isn't very elegant. If one service is down (or worse, very slow) your API slows down. And perhaps that business logic is not appropriate to house in the controller either. Polly is designed for dealing with failures, but how to use Polly in this situation is not completely trivial.
@ChrisWard74
@ChrisWard74 2 месяца назад
I was hopeing for a demonstration of this too. If the first one is down or rate limited how do we get it to use the second gracefully.
@KnightSwordAG
@KnightSwordAG Год назад
I would add one use case I see frequently that this solves more elegantly. We use a lot of Dapper here, and so our services regularly need an IDbConnection, but sometimes to two differrent databases (different connection strings). Because a service or repository class needs an IDbConnection, currently, we have to do a lot of extra work at the DI registration to figure out which IDbConnection we need for the service we're calling. With this, we can declare at the service's constructor which IDbConnection we need, or expect. Or at the DI registration, get the keyed service before calling the service's constructor.
@Fred-yq3fs
@Fred-yq3fs Год назад
Scary! Your container should not contain any app logic let alone any complex logic. It's not the job of a container, it's typically the job of a factory. Keyed services are simple factories. It's sugar to avoid writing a factory. If you find yourself calculating the key in your callers, then that scattered logic would better live in a factory. If your client passes an enum and it alone decides which implementation to use then fine: use keyed services and write less code.
@Nworthholf
@Nworthholf Год назад
In that case connections to different databases should be under their own respective interfaces tho, otherwise you are defying the point of using DI
@KnightSwordAG
@KnightSwordAG 10 месяцев назад
@@Fred-yq3fs you misunderstand. It ultimately becomes a factory of keys to db connections. And it always seemed weird to me to pass the factory as a dependency to a class that only needs the connection.
@MrEnvisioner
@MrEnvisioner Год назад
Am I missing something as to why a "keyed" service with an alias is preferable to just explicitly registering the service by its own type when you want to request a *specific* instance? If not that, then as others mention, a factory that handles resolving the service for you is the smartest and most reliable solution. I dont really get why someone would even need something like this.
@Stealthy5am
@Stealthy5am Год назад
One reason for not registering and resolving by the concrete type is you'll not be able to mock these dependencies in unit tests. Alternatively, you can make a "sub-interface" for each key, but then you end up with marker interfaces, which is not much better. Although, I do think this feature is mostly just bloat and the problem can easily be solved by using factories as you mentioned. In my experience, this problem does not come up often enough to warrant bloat in the library, but MS probably has more data to justify their decision.
@stevenodlum4563
@stevenodlum4563 Год назад
My assumption would be for unit testing. Decorating the interface with the alias just tells dotnet to use a specific implementation when the API is running normally, but you can still manually provide mocked services for unit tests.
@justgame5508
@justgame5508 Год назад
Less abstraction I guess, this doesn’t require a factory with some CreateClient() logic and a class to go along with that to resolve a service. It’s just the service you want and a name, which has its benefits (less indirection). Then again I think this syntax in the constructor parameters is ugly so I’d personally chose a factory over this
@vonn9737
@vonn9737 Год назад
@@Stealthy5am You can register both with their own interfaces which inherit a base interface. IOpenWeatherApi : IWeatherBase and IWeatherApi : IWeatherBase. So that's no problem.
@gileee
@gileee Год назад
Cause Java Spring has it...
@a-minus-b-equals-a
@a-minus-b-equals-a Год назад
While interesting, I can't think of a use case for this. In a scenario like the one you've described, I feel a better solution would be to create a singleton wrapper class that takes in IEnumerable and cycles to the next service whenever a 500 is returned(or any other "cycle to next" conditions). That would allow setting up a variable amount of backup services without requiring the usage of keys.
@tkrafael
@tkrafael Год назад
Suppose you have a multi tenant system that checks for user's phone balance. Whenever your api is called, you have to call balance api on carrier's api. That api does not have a default contract, to the point done aren't even using http/rest. By using keyed service, you are able to resolve a specific implementation from user's carrier.
@a-minus-b-equals-a
@a-minus-b-equals-a Год назад
@@tkrafael I might be missing something here. If, from the same API route, we want to get a different service based on the caller's carrier, how would it work with this system, given that the keys are hardcoded? The only way I can see this working is if we use a proxy wrapper class/dictionary to map to the correct service, rather than specifying a hardcoded key for endpoint.
@sebastianxx3687
@sebastianxx3687 Год назад
how about for example as part of strategy pattern ? 1 payment interfaces - 3 different implementations in 3 different services
@a-minus-b-equals-a
@a-minus-b-equals-a Год назад
@@sebastianxx3687 If the different implementations need to have a distinct identity, imho it'd make more sense to add an intermediate interface to distinguish between them. So, if you have multiple IWeatherService that need to be distinguished from each other(maybe by a proxy factory class which then returns them as generic IWeatherService), instead of [FromKeyedService("openapi")], you'd implement an interface that inherits IWeatherService, so you'd request IOpenAPIWeatherService instead. The end result is about the same, so using keys just feels like a weak-typed alternative.
@Nworthholf
@Nworthholf Год назад
@@sebastianxx3687 its not a container's concern to choose strategy. Binding it that way denies you the main purpose of using DI, which is implementation agnosticism
@petewarner1077
@petewarner1077 Год назад
Used to use Autofac back in the day, and while I understand adding this for completion, it's not been a feature I've missed. Having to annotate the dependency requires knowing the key at design time, which feels (to me) like it violates the idea of "inversion of control". When I've had a use case to use one of N implementations in the past, I've just registered a good old factory delegate that would hand me the registered service I needed based on the function parameter I passed in. Having said that, it does allow a neater method for creating decorators instead of using something like Scrutor or rolling your own decorator extensions.
@tkrafael
@tkrafael Год назад
Using a factory might violate service locator anti pattern. And because method/constructor signature doesn't have explicit dependency fire that service (only to factory) it would be harder to test and troubleshoot missing dependencies
@petewarner1077
@petewarner1077 Год назад
@tkrafael I don't think it violates that because the delegate merely chooses a service implementation based on inputs, like moving a switch statement out of inline to the container. The client code doesn't take a dependency on IServiceProvider, just a Func.
@ddruganov
@ddruganov Год назад
if you hardcode a key when requiring a service through di then what is even the point? why not inject the service directly without an interface?
@PublicVoidFoo
@PublicVoidFoo Год назад
The main reason would be so that you could still mock your dependency in unit tests
@ddruganov
@ddruganov Год назад
@@PublicVoidFoo okay yeah makes sense thanks
@kaizer-777
@kaizer-777 Год назад
Another work-around is to inject a factory class that can resolve your dependency based on whatever key as well. This new approach would be a little cleaner though.
@briumphbimbles
@briumphbimbles Год назад
I would still prefer a factory over this.
@metaltyphoon
@metaltyphoon Год назад
Or if you don’t need to mock, just registered a class without interface.
@sheveksmath702
@sheveksmath702 Год назад
Just curious, but why would you prefer a factory over this?
@kaizer-777
@kaizer-777 Год назад
@@sheveksmath702 I wouldn't. I was pointing out another work-around.
@JonWoo
@JonWoo Год назад
I would also prefer a factory over this. This approach has the controller deciding which service to use.
@Nworthholf
@Nworthholf Год назад
I genuinely hoped they will never bring it to default DI. It is quite an antipattern that breaks the whole point of using DI, which is explicitly about _not_ specifying desired implementation. Loose coupling goes straight out of the window with the "keyed DI" approach.
@jelle2819
@jelle2819 Год назад
Agree, the cases people use this for tend to be fragile and non intuitive. Even Nick falls for that. I have seen layers of cache, dbcached and remote layers as adapters. And then somebody forgets to use the key. They just get one... but wich... all uses of keyed injection result in a huge nightmare. I'd happily write an analyser that flags this feature as a design error 😂
@user-nq8ln7ps7x
@user-nq8ln7ps7x Год назад
Back in the day Ninject has different approach for that. It was something like Bind().To().WhenInjectingInto(x => *filter*); //or WhenInjectingInto() And that was better, because you still manage your dependencies in startup, and not hardcoding some "alias" in your dependent class. As other comments mention, approach with Keyed/Named services is not any better than just binding different services to different (inherited) interfaces - dependent classes should know that they want, they should known name/key/alias.
@dobripopov8466
@dobripopov8466 Год назад
Definitely the Ninject approach is better. It is container's responsibility to inject the correct implementation of a specific interface. The "consumer" should NOT be aware of what instances have been registered inside the container and to know their keys/names. Hopefully it's not too late for Microsoft to redesign their DI framework before the release in November.
@EikeSchwass
@EikeSchwass Год назад
I would really love for custom resolve methods. For example Would prefer to have a class A { A(ILogger logger){}} instead of class A { A(ILogger logger){}} and have it resolve depending on what type it targets
@mkwpaul
@mkwpaul Год назад
I really don't like the idea of having to modify some implementation in order for the dependency injection to work as expected. If I write a service to call some API, read from a db or do literally anything else, it shouldn't concern itself with how it is treated by some other part of the code. It should simply demand its dependencies and expose its functionality. And I don't need a DI container to implemenent any service itself. In this example I think I'd much rather have a third IWeatherService implementation which takes a number of implementations and contains the logic of when to choose which and fowards the interface calls and then just register that one. You could alternatively have a WeatherServiceResolver service that does the resolving and returns the chosen implementation. Although that would have the same issue as the keyed stuff. Anything that needs a weatherService, needs a weatherservice and shouldn't concern itself with the fact that I might wanna dynamically choose between different implementations, or that I use a DI container.
@AhmedMohammed23
@AhmedMohammed23 Год назад
sweating from 20 degrees i would like to invite you to my house in Egypt 😅 20 is when i wear my winter clothes
@dirkp.6181
@dirkp.6181 11 месяцев назад
Caution with usage of keyed/named services, because it might introduce code smells. If the services are meant for redundancy, they are necessarily _semantically_ equivalent. Hence it should be transparent for the consumer and the consuming code should not be forced to chose. To implement redundancy is a separate, technical concern. Create some wrapper with polly for instance, but keep the consuming business code clean! However, if the named services convey different semantics, they should probably be distinguishable not only by some config name, but rather by an interface. Also note, that the naming introduces an dependency, that DI is exactly meant to overcome! "Ask for a fulfilling service and _don't_ care for the implementation!" I confess that I felt like reaching out (in rare occasions) in the past for named services in DI, but meanwhile when running into this it rather makes me think twice.
@JerryFederspiel
@JerryFederspiel Год назад
Thanks for mentioning Scrutor! For needs like caching, retries, etc., I've always manually wired up decorators, and it looks like Scrutor should make that much cleaner.
@jfpinero
@jfpinero Год назад
I use scrutor to decorate services that need caching, works really well the [Decorate] attribute.
@ryancookparagliding
@ryancookparagliding Год назад
Not a fan of this feature - I don't like attributes and I reckon the enumerable route with a CanProcess() on the interface is cleaner and also easy to test. Guess there's situations it's useful like heavy service constructors, but I'd argue there's a design problem to consider? Always good to know though - thanks for sharing 🙂
@wojciechwilimowski985
@wojciechwilimowski985 Год назад
Can you then inject Dictionary and pick your service out in the constructor? The attribute looks clean and all, but it looks like most of the benefit is lost if I have to hardcode the key
@jamesmussett
@jamesmussett Год назад
I do like the idea, but I personally wouldn't use it. Mainly because it tightly couples your code to the DI framework itself (in this case, Microsoft.Extensions.DependencyInjection.Abstractions). You can achieve pretty much the same thing, albeit not as elegantly, using the factory pattern.
@bladbimer
@bladbimer Год назад
Good honnestly it was the major issue I faced with D.I and as mentionned below I was using factory methods or some functions to provide the good implementation based on key. I reallly hope this will be implemented everywhere (I mean for Worker services, API, Blazor etc.)
@pavfrang
@pavfrang Год назад
A factory is the best of all worlds, in order to create any different type of instances. Thanks for the great presentation!
@rogeriobarretto
@rogeriobarretto Год назад
When you started talking about backup weather services I was thinking the DI would be able to understand what service is healthy as well and return it accordingly. That said, would be interesting if they could expose a interface to help how to resolve which service in case of multiple ones. I believe we would need a intermediary/wrapper Backup IWeatherService that gets both Weathers to property resolve which one to use. That would be an interesting example!
@davidbottiau5408
@davidbottiau5408 Год назад
I thought the same too. But at the same time I was thinking "How could that even be possible?". If it was possible, it would be magic. However, giving the IEnumerable of registered interfaces, I suppose we can code our own wrapper that will select the best implementation based on your needs. Like exporting a "Ready" instance property. Not sure if DI is abolutely necessary in this context but It's doable.
@paulmdevenney
@paulmdevenney Год назад
If they are both singletons then you are actually probably better having an "IsHealthy" ,getting the IEnumerable and chosing the best matching healthy service.
@tkrafael
@tkrafael Год назад
For those scenarios, I use scrutor library so I can stack implementation and be able to call as decorated classes
@m_rray
@m_rray Год назад
Thanks for the video! My only thing is that I wish you’d named the two keys and variables differently. I know it’s not the main focus on the video and it’s just an example in context, but ultimately people will, and do, use these videos as examples. Keying and registering services based on implementation is very leaky. Ultimately you have an interface and any concrete implementation could be used, the consuming code should not know about the implementation. I would generally prefer the use of an enum for example with the values of say “Primary”, “Fallback” etc, and then grab the primaryWeatherService and the fallbackWeatherService. They don’t care about implementation then. In this example, imagine you decided that the weatherApi was now your preferred api, you’d have two choices: one to swap the keys so that they no longer matches tbe implementation which is highly confusing, or go in and edit existing stable tested code to get it to use the weather one first and fallback to open weather - violating the open/closed principle. Using the generic naming all you’d need to do is, in the application root, switch the enum values around so Fallback is now Primary, and then that will be used as the primary, the assignment still makes sense, and we haven’t had to edit lots of code.
@StephenOwen
@StephenOwen Год назад
Today we handle this by having an interface that all of our implementations use, one of which is a public enum value. Then our services that might need one or the other request an IEnumerable from Dependency Injection, and then in their constructor pick the one they need. It will be nice being able to do this natively!
@Arcadenut1
@Arcadenut1 Год назад
If you're looking for fail-over then I would expect the IEnumerable would have been a better solution. You try the first item and if it fails you move to the next. Doing the Keyed services you have to know ahead of time all the different services that were registered.
@andrewmcclement4464
@andrewmcclement4464 Год назад
Perhaps this is better if you want a strict priority between the services, i.e. you care about the ordering.
@VeNoM0619
@VeNoM0619 Год назад
The less 3rd party dependencies the better. Especially if its native C#, since importing 3rd party dlls etc. into cross platform apps can be difficult still (Unity3d). I feel like the native libraries are part of what makes languages take off. Python comes to mind, even though honestly I never fully touched it, but everyone says it can do anything. I also recall some unix libraries having that same adoption rate when they became a jack of all trades.
@trevorwilson7012
@trevorwilson7012 Год назад
Personally, I liked the fact that they didn’t implement this feature. If you’re going to bind to something concrete you might as well just bind to the concrete type, rather than use a key to bind an interface that binds to a specific type. This just seems backwards to me. Thanks for sharing though.
@Fred-yq3fs
@Fred-yq3fs Год назад
I used to like the autofac keyed service. But... resolving one implemention is part of the application logic, so it should not be part of the container. In that case, I prefer to use a factory so I'm explicit about resolving. Sometimes the factory is as simple as a key, so granted: factory might be overkill... but more often than not logic creeps in, and that's when factory is the right approach. You really don't want to let app logic creep in the DI setup, especially because it's harder to unit-test. Think refactor cost and risk: if not covered by a unit test you might not dare to refactor, so you're stuck in legacy code, just because you chose to use a fancy feature at some point.
@SlackwareNVM
@SlackwareNVM Год назад
"I wanna know your thoughts on the topic." Me: ... FINALLY!
@TechAndMath
@TechAndMath Год назад
In the context of my daily work, we solved this from a business perspective and never need two have multiple service suppliers for the same piece of data. 1. Make sure that our service supplier is not just running the service on one server (can be done via SLA or contract discussion) 2. Make sure that our service supplier has a SLA which guarantee a level of up time and performance time that is acceptable for us As our service suppliers are mainly fairly big boys in their field, we haven't really seen the need to plugin an alternative supplier up to now. Some times their system may go down, but that is within their SLA and our SLA, so it is something can be tolerated. Multiple suppliers always trigger data consistency and its own maintenance issues. So I feel that it is better to be handled by business perspective.
@PereViader
@PereViader Год назад
I don't really think saying "we avoided the problem" is the same as coming up with a solution 😅
@TechAndMath
@TechAndMath Год назад
Basically the business made the decision or solution and it worked better than a pure dev lead one in this case
@dimitrishadrin
@dimitrishadrin Год назад
I needed this feature always. And now I use factories or implement my version of keyed wrapper. In new implementation I don't like attributes, in my opinion it should be configurable without attributes. And fully agree about decorators and convention.
@egida6486
@egida6486 Год назад
@nickchapsas Don't you couple your method implementation, to a specific service implementation that way, which defeats the purpose of IoC? Keyed Service seems like a step backwards to me. For such usecases I'd prefer the "inject IWeatherServiceFactory" approach, and put the service selection logic into the factory, instead of relying on a DI-Container feature.
@diadetediotedio6918
@diadetediotedio6918 Год назад
Nah, this is just untrue. See, the same key can be static and the concrete implementation be different, you can use it as a guide.
@egida6486
@egida6486 Год назад
@@diadetediotedio6918 if the key is used (reused) it means it is a marker for an abstract concept, which would justify its own interface. if its used to pick out specific implementation from the container, its the service locator pattern and IoC is voilated. Keyed Services still seem like a step backwards.
@Nworthholf
@Nworthholf Год назад
@@diadetediotedio6918 if anything, it makes you incapable to mock the selection logic anyway
@jwcodendaal
@jwcodendaal Год назад
Hooray. Been using that for years in autofac. Used a factory recently to acheive that in one project. Nice to have it there now though
@snapching
@snapching Год назад
I would add that this is a component or plug-in architecture. My preference is to have an attribute on the interface which provides the "key" differentiator. Concrete classes would then define the key rather than the class key provided during registration with the IOC container. Then do ienumerable of the interface in constructor, and in code select the preferred implementation based on business logic.
@lucasterable
@lucasterable Год назад
Complete my foot! Wow they still havent implemented: - decorator pattern - interceptors - named instances Amazing how behind .NET DI is in 2023
@nertsch77
@nertsch77 Год назад
Probably, the title is wrong. It should be called "DI-Container is now complete..." since Dependency Injection does not require a DI Container
@nickchapsas
@nickchapsas Год назад
Obviously but titles after a specific length are cropped and DI isn’t picked up by SEO so it had to be that
@sua01n
@sua01n Год назад
Great improvement, now I can replace my own written workaround with that :-)
@Igahwanoiar
@Igahwanoiar Год назад
IDK, I used to intuitively tend to solutions that had keyed registed services, but it never really felt right. The whole point of interfaces is that the dependency is on the service, and the implementation doesn't matter. But if the client needs to pick which registered service is used, doesn't it technically make it a different service? I started using this other methode. It's fair to call it boilerplating, but I wouldn't call it a workaround: just make an empty interface for every named service and have it extend the original interface. No magic strings, no assembly scanners and you get exactly the service that you need, using regular DI.
@samuelschwager
@samuelschwager Год назад
Pro: no interface inflation; Con: magic strings. I guess whether or not to use it depends on the use case.
@Nworthholf
@Nworthholf Год назад
Its fairly simple - you should never use that thing.If you are going that way you can just as well instantiate everything in place without using DI container at all.
@maximer.8190
@maximer.8190 Год назад
What about creating two interfaces IWeatherApiService and IOpenWeatherMapService, both inheriting IWeatherService? If you have to specify the key where you require the service, it looks the same to me.
@miguelduarte75
@miguelduarte75 Год назад
Can't think of any use case for this feature but thanks for sharing
@gamedev_expert
@gamedev_expert Год назад
Hi! Don't understand the reason to bind two impl for one interface and then resolve by key. For me it's look like missing L from SOLID.
@diadetediotedio6918
@diadetediotedio6918 Год назад
You don't need to force everyone to chase your rules when programming bro, just don't use it. But it is not incompatible with SOLID at all, this is good for the O, I and D of SOLID.
@qj0n
@qj0n Год назад
Adapters to external systems don't always conform with SOLID, it was meant more for domain level IMO Better example would be to have multiple queue clients connected to different queues - since you use one library, they all have the same interface, but are configured in different way
@gamedev_expert
@gamedev_expert Год назад
@@diadetediotedio6918 not forcing, but trying to learn something new
@mistermeua
@mistermeua Год назад
I can not find a good case where i could use this feature for any of my projects now or in the past. I feel itching that we are to spread constant strings around (looks "meh" as for me no matter how you wrap it...) As for me, I'd better inject some factory that relies on some non static (e.g config) props for resolving stuff I need. As other comments suggest. But maybe I just don't yet faced a case when I would need it...
@samysammour9983
@samysammour9983 4 месяца назад
Finally! It took a while though but hurray.
@RealDicko
@RealDicko Год назад
You could do this before using a generic in the interface like an enum. I think it's more advantageous if you could use the key inside the ctor so you can use do something like use a database value for the key to dynamical change it.
@lyrion0815
@lyrion0815 Год назад
I would register the OpenWeatherMapService without a name, and the fallback one with "fallback". The OpenWeatherMapService would have to be registered last so its made the default by the IoC Container. Depending on the use case I would just resolve an IEnumerable and use the data of the first one that works.
@tryagain6148
@tryagain6148 Год назад
This feature also existed in Unity DI (still Microsoft), and it was way over abused. I prefer to avoid this kind of scenario by adding an identifier to the interface I'm registering that is implemented by the implementation class. In this way, I can do the factory filter in my code... without relying on the DI to do it for me. You know you're screwed when you notice that over 400 instances are name registered in just a simple application.😂
@Jadenity
@Jadenity Год назад
What perfect timing for this. I have a situation that out came up that this fits perfectly. However, I'd like to know what the best way to do this in .NET 6 is (without using AutoFac).
@alexisfibonacci
@alexisfibonacci Год назад
I make my services implement a key and then add them to the DI using add multiple. Then when needed GetServices() which returns an IEnumerable which I can then filter with LINQ and pick out the desired one. He went through that around 5:00
@Didymus888
@Didymus888 Год назад
Just use a factory
@logank.70
@logank.70 Год назад
I was really hoping it was interceptors. It's really nice being able to add logging to things without having to pepper my code with log statements everywhere. That's the one feature I'm still waiting for.
@ldlework
@ldlework Год назад
Use the decorator pattern (I don't mean "decorators")
@logank.70
@logank.70 Год назад
@@ldlework That does definitely work. It's just nice to be able to define something like logging or performance metrics and be able to attach it to whatever you want without having a bunch of decorators for the different things you want to decorate. Although that could be a naive approach to decorators.
@traviscoleman8810
@traviscoleman8810 Год назад
This feels like a very complicated way to have interfaces, but work around them. Also, this looks like it would make for messy unit testing.
@kabal911
@kabal911 Год назад
Don’t see how this in anyway affects unit testing, considering that wouldn’t even run though the DI container, and you are still mocking an interface
@emerynoel567
@emerynoel567 Год назад
This does not seem very useful to me, since the key is hardcoded into the injection site. What would be preferable is logic to determine. I have worked on a system with "tenants", where tenants may have their own services. (This was for an insurance company, where each 'tenant' had their own policy system, so we needed to inject services depending on who was calling.) We were able to achieve this with a non-default container, but I don't remember which one it was. EDIT: It was "autofac" I think?
@KJ1987pl
@KJ1987pl Год назад
Yeah, for me is great news, generally, I'm always against adding big libraries to projects, especially when they have native support, less dependence is better for all of us (I'm talking about programming only 😅)
@RamonDeKlein
@RamonDeKlein Год назад
The question is whether you should use this feature like this. Creating an intermediate provider interface would make much more sense and also makes testing easier.
@Astral100
@Astral100 Год назад
Wow, finally, I've been waiting for something like that for ages! It always bothered me that you can't use interfaces as they were originally designed to be used to in the Microsoft's dependency injection.
@haxi52
@haxi52 Год назад
It really feels like the consumer knows too much about the dependency using this feature. As other have pointed out, there are better ways. I would like to see a real work production app that would use this. To me just have two interfaces that implement the 'base' interface and register those. Seems like a cleaner implementation.
@sumitsinghdeo5466
@sumitsinghdeo5466 Год назад
Its really nice one, I request you to have a session on IAsyncEnumerable implementation and usage. Thanks for sharing the knowledge with us.
@lyrion0815
@lyrion0815 Год назад
For me, this features is an absolute minimum requirement for a IoC container (along with a few other features the built-in IoC is still missing), I just added autofac to my projects as soon as I had the requirement for it.
@Nworthholf
@Nworthholf Год назад
..but this "feature" is a horrible antipattern that should have never made its way to msdi
@Kevmoens
@Kevmoens Год назад
The one feature I didn’t like was if you need an inline resolution you have to pass the IKeyedServiceProvider through the constructor verse having a way to get a resolving class that is by the interface so you can see in constructor what your dependencies are
@nikitaklimchuk5032
@nikitaklimchuk5032 Год назад
I don't like service being dependent on DI container, especially these Attributes, it doesn't allow you to reuse a service using another implementation of interface. Also, it misses "rules" functionality comparing to DryIoc, for my use case - I want to reuse a service using specific key, and I want all nested services to be resolved using that key, doesn't look like it will be possible to do.
@everyonesview
@everyonesview Год назад
I have been using Autofac for this until NET 8. Grand! One less external dependency.
@ukapas
@ukapas Год назад
Is there any compile-time protection from mistyping the key?
@detach8
@detach8 11 месяцев назад
Isn’t the whole point of DI to remove dependency on specific implementations? By adding keys/removing interfaces we are making the code tightly bound.
@matthias916
@matthias916 11 месяцев назад
i always used factories for this, if im understanding this correctly this would be just like having a factory except you dont have to create the instances yourself?
@allinvanguard
@allinvanguard Год назад
About time, this essentially means that other DI providers like Autofac are basically obsolete since they only provided keyed services and some very advanced and exotic use cases like interceptors. But right now, for 99% of my apps, I wouldn't really need these capabilities anymore. Happy to see this in MSDI finally.
@johan.mp4
@johan.mp4 Год назад
Intereptor/decorator can be achieved in the standard container with just a few lines of code. You don't need a separate library for that.
@allinvanguard
@allinvanguard Год назад
@@johan.mp4 Oh, my bad, I meant "Missing binding interceptors", not plain interceptors / decorators. That works pretty well already.
@catq_q6233
@catq_q6233 Год назад
It's a step in the right direction, for sure, but for Autofac to really become obsolete MSDI still needs to add a lot imo, starting with property injection...
@Rein______
@Rein______ Год назад
​@@catq_q6233please no property injection 😢. Does not work right with nullable
@celluj34
@celluj34 Год назад
@@catq_q6233 You cannot convince me that property injection is not a code smell.
@_iPilot
@_iPilot Год назад
Does it support injecting multiple implementations as IEnumerable of the same key if several is registered with that key? Or keys must be unique?
@eclecticx
@eclecticx 5 месяцев назад
You have good and informative videos, but you should seriously consider a slower cadence. As for this example in particular, it seems to break SoC (antipattern), has some naming issues (implementation rather than purpose), and depends on hard-coding.
@TonysRacing600
@TonysRacing600 7 месяцев назад
I still don't understand the benefits of those Singleton Services over static variables you can reference.
@florent9555
@florent9555 11 месяцев назад
Hey, could you not solve your singleton problem with generic interfaces? For example IWeatherService and IWeatherService
@garcipat
@garcipat Год назад
This does not seem to do the same as injecting IEnumerable and filter since you cannot chose on runtime what implementation you want. I often have an Enum wnd different implementation depending on that. Means I need a Func to get the according service during runtime because it may comes our of the configuration or so. Its one Step late.
@notoriouslycuriouswombat
@notoriouslycuriouswombat Год назад
so the default is always the last registered? kinda wish there was a way to register, and say "this is the default" that way the default is not position dependent
@Nezbo
@Nezbo 10 месяцев назад
Is/will there be a way to get TService[] allOtherImplementations without having to know the keys of other services registered under the same interface? Or Dictionary with the keys.
@ldlework
@ldlework Год назад
Doesn't this violate the open-close principle? The dependent class now needs to statically refer to its dependency (albeit through the key alias). If you wanted to change the behavior of the dependent, you'd have to come in here and modify it. I think in a real scenario, you would not be using the key to identify specific concrete implementations, but rather "flavors" of implementations, like "cached" or "uncached" as you mentioned.
@Nworthholf
@Nworthholf Год назад
It absolutely does, and if you are using that you might just as well do back to instantiating everything in place
@kenjohnsiosan9707
@kenjohnsiosan9707 Год назад
thanks and, you didn't show how it would automatically resolve services at runtime when say for example the first service fails.
@Crossbow123
@Crossbow123 10 месяцев назад
Its still missing property injection. Now that we have required properties, this feature is begging to be here.
@DannyEck
@DannyEck Год назад
My (brain) at 2:38: "the real f__cking API" (that couldn't be right, rewind 10s) "the real bucking API" (Is that UK slang?, rewind 10s) "the real backing API" (Oh. I'm an idiot)
@robslaney3729
@robslaney3729 Год назад
IMHO the "key" dependency is the wrong way around. It should be a registration concern, not the resolved. Same issue as base classes having to know about their derived. Worked successful with Unity DI container for years, the resolved instance never had to worry about which implementation it got. Think about conditionally adding a cache wrapper. By using an attribute I have effectively decided at compile time which one I get.. or I change the registration to match what is being requested.. which basically defeats the purpose. Can I use the keyname when I resolve, like with ActivatorUtilities, or registration factory lambda? Will resolving IEnumerable retrieve all the instances, both non-keyed and keyed. If I resolve without the key attribute, will the existing behavior apply that includes key-ed registrations in the last-in best-dressed eval? The biggest issue I have with MS's ServiceCollection is the lack of ability to use a factory with an open generic. You can't get the type(s) being used to resolve. Not common, but very handy when the need arises.
@daddy2claire
@daddy2claire Год назад
Resolving a service by name.... isn't that Service Locator - usually considered an anti-pattern?
@colindawson4818
@colindawson4818 Год назад
I'm going to stick with AutoFac. I've used it for many years, without issues, and don't see any compelling reason to change. The ultimate king for me is performance, and not just at a theoretical level. I'd need to see a practical implementation where it actually makes a big difference in a real world scenario.
@user-dq7vo6dy7g
@user-dq7vo6dy7g Год назад
stronginject might be a good thing for performance. I understand he/they do the injection at compile time. If you take a look let me know, I have this in my bookmarks for months 😄
@user-zk5ym9ut1j
@user-zk5ym9ut1j Год назад
I've seen benchmarks thay show that built-in DI is faster than Autofac
@ricmrodrigues
@ricmrodrigues Год назад
Main problem with that, which I want to as well, is they've made the built-in in such a way you can't take it out. A bit of a conforming container and a leaky abstraction.
@alexvanheerden5702
@alexvanheerden5702 6 месяцев назад
Strings passed to Attributes must be constants, so how is this different from just injecting the concrete type?
@Crozz22
@Crozz22 Год назад
async is a pretty big thing missing
@qj0n
@qj0n Год назад
MSDI was always meant to be a simple DI interface, which you can easily override with your own implementation, so you can easily use any container you want. I'm worried that if they add more and more features to it, it will be harder to replace it or some features will be missing with some implementations. It would defy the whole reason to create MSDI
@temp50
@temp50 Год назад
I'm not sure if I get it. If we are acquiring the given service by its actual type then why are we trying to register them by the interfaces they implements.
@riccarrasquilla379
@riccarrasquilla379 7 месяцев назад
thanks for the video
@pranavraj4655
@pranavraj4655 Год назад
I love this change. 😊
@yurymatsiulka5786
@yurymatsiulka5786 Год назад
I prefer to work with keyed services when an entity or contract has a discriminator
@alextelegin6467
@alextelegin6467 Год назад
Well, 10 years later we might get brand new features like dependency validation and captive dependency check)
@ivandrofly
@ivandrofly Год назад
Good one, thanks :)
@bradenb
@bradenb Год назад
I don't get the usefulness. I want my interfaces to hide my implementation, so why add an attribute (also yuck) to then request a specific implementation? I'd much rather just inject the concrete type, or even better, just have a more specific interface. Another commenter mentioned that this could be for purpose rather than implementation; fine, but is this really the way to solve that problem? You could have a service dedicated to providing instances dynamically based on purpose rather than tie purpose to a compile-time decision. What's the use case for this?
@paulalves966
@paulalves966 Год назад
Castle Windsor DI have that for at least a decade! 😌
@paulalves966
@paulalves966 Год назад
More 10 years and we may get mixins, property injection, conventional registrations, and MEF 😂🎉
@Gallardo994
@Gallardo994 Год назад
To be fair, I dislike built-in container simply because Ninject feels nicer to use in any dotnet application, even console one. It is a one-liner for the initialization part, and it is easy to split code with modules
@TECHN01200
@TECHN01200 Год назад
IMO, DI needs to either die or spit out a compiler error if a DI dependency isn't registered, but given that this is just a library and not a language feature, I'm not holding my breath for that compiler error.
@TheDimasik9281
@TheDimasik9281 Год назад
Hi, NativeAOT work for window form?
@niranjanjyothi2416
@niranjanjyothi2416 Год назад
How about the existing NamedSingelton?
@AndersReinhardtHansen
@AndersReinhardtHansen Год назад
Could this be used in conjunction with featureflagging, where you would use versioning or some other functionality to choose which service to use?
@Ehomer0815
@Ehomer0815 Год назад
Just bought your new course but it doesnt work :( Only white screen after starting it
@PiotrKula1
@PiotrKula1 Год назад
I wish they never added this. This breaks IoC as you are asking for specific implementation at compile time. The IEnumerable way which you call "mehh.." at least you can guard and key of at runtime. So you can pick services by config / from db . Id rather they did the DI by convention so we dont have to use Scrutor
@raindev88
@raindev88 Год назад
some devs would get amazed by this rather than writing their own factory implementation which is a headscratcher for a few.
@leonardomoreno23
@leonardomoreno23 Год назад
Goodbye Scrutor. It was a pleasure ❤
@ahmedbenissa5982
@ahmedbenissa5982 5 месяцев назад
This was still achievable before .net 8 using factory lambda expression
@nooftube2541
@nooftube2541 Год назад
Top feature. Sad that our architects not good with di and force app developers to use statics or other self written approaches.
@ryancookparagliding
@ryancookparagliding Год назад
haha that's wild 😅
Далее
Making Your APIs Blazingly Fast in .NET 8!
11:45
Просмотров 68 тыс.
The Free Way to Create Awesome PDFs in .NET
12:45
Просмотров 34 тыс.
OG Buda - Сабака (A.D.H.D)
02:19
Просмотров 134 тыс.
Background Tasks Are Finally Fixed in .NET 8
10:29
Просмотров 109 тыс.
The Smart Way of Using the Decorator Pattern in C#
12:37
.NET and C# are in trouble. Here is what I'd do.
10:57
Don't Use Polly in .NET Directly. Use this instead!
14:58
When RESTful architecture isn't enough...
21:02
Просмотров 275 тыс.
Don't throw exceptions in C#. Do this instead
18:13
Просмотров 258 тыс.