Timeline for How to register multiple implementations of the same interface in Asp.Net Core?
Current License: CC BY-SA 4.0
42 events
| when toggle format | what | by | license | comment | |
|---|---|---|---|---|---|
| Nov 7, 2024 at 21:34 | comment | added | Skystrider | There's services.AddKeyed[thing]("key") where [thing] can be Scoped/Singleton/Transient as per your need and "key" can be other kinds of objects too. Then you can use a factory that has IServiceProvider injected and you can do _serviceProvider.GetRequired[thing]("key") | |
| Aug 21, 2024 at 13:25 | review | Suggested edits | |||
| Aug 21, 2024 at 15:14 | |||||
| Aug 18, 2024 at 22:56 | comment | added | Silent Fart | @ClemB Hereβs one I did with .NET 8: gitlab.com/ShirazAdam/RuntimeComposition.NET | |
| Mar 20, 2024 at 14:00 | review | Suggested edits | |||
| Mar 21, 2024 at 19:18 | |||||
| Feb 27, 2024 at 9:46 | comment | added | ClemB | The answer should be updated with the new .NET8 keyed dependency injection learn.microsoft.com/en-us/aspnet/core/fundamentals/… | |
| Nov 9, 2022 at 23:35 | comment | added | Eric Eskildsen |
@PiotrKula Ah, so what you're objecting to is the answer's suggested Func implementation with switch more than Func itself (or let's just say any function), yes? Because using reflection is still writing a factory that you'll need Func or a class for. There's just no switch. (I say "just," but I agree it's an improvement with regard to open/closed past a certain complexity.) At first I interpreted your comment as, "There's a built-in way to do this with the MS DI framework that eliminates the need for a custom function completely," so that's what I was curious about.
|
|
| Nov 9, 2022 at 23:01 | comment | added | Piotr Kula |
@EricEskildsen I still would not use Func<> directly like that even today. What I would do is something along the line of MetaProgramming (Reflection) and look at type matching or expression matching. In your case though I would apply the Actor Pattern - So you can register multiple concrete commands under the ICommand interface and then your processor works out which command/s from the injected IEnumerable<ICommand> to run - I am literally doing (something more or less) like that now. ππ
Either way no Func'y business needed!
|
|
| Nov 9, 2022 at 16:22 | comment | added | Eric Eskildsen |
@PiotrKula I think this is still useful with Microsoft's current dependency injection framework. Consider this: You're implementing the command pattern with multiple command classes. Users can run commands. Their requests are stored in a database table, including the command's type and arguments. Now you're writing code to execute user requests. The code reads the request from the database, then needs to resolve it to a concrete command class. How would you wire that up without a Func or an equivalent class?
|
|
| Jan 13, 2022 at 2:32 | comment | added | Josh Gust |
I disagree with the premise of a consumer locating a dependency by magic string. A consumer that must know about the implementation (here abstracted by magic string) is the opposite of Dependency Inversion. If the consumer will "break" if it doesn't get the right implementation then you're not really using the strategy pattern. Register those implementations as individual TService interfaces. Try not to reuse TService when registering unless your using patterns like the chain of responsibility where the consumer can handle ALL the items in IEnumerable<TService>.
|
|
| Jan 13, 2022 at 2:09 | comment | added | Josh Gust |
@user2243747 your fly resolution is always null b/c you're asking the provider for a TService of Aeroplane, but the only TService your provider only knows of is IFly. In your example Aeroplane is a TImplementation. If you want your implementation to be registered as a service you should use .AddTransient<Aeroplane>(). Then to use the service locator pattern shown in this answer to diff between those implementations on some key.
|
|
| Feb 13, 2021 at 23:18 | comment | added | Jacob Roberts | Down vote explanation - I agree with @PiotrKula and have a full implementation in my answer below. We can remove the notion of the key in a very easy way. Check my answer below. | |
| Feb 10, 2021 at 8:38 | comment | added | R. V. |
Using typeof(Class) operator you can also create Dictionary<string, Type> types and then use serviceProvider.GetService(types[key]) in order to avoid the switch.
|
|
| Feb 2, 2021 at 4:33 | comment | added | Skip Saillors | @Mukus The ASP.NET Core DI container doesn't allow you to inject the service you want in a straightforward manner, true. Core DI does simple injection simply. Complicated injection scenarios are tricky using Microsoft DI. Other DI frameworks offer other methods to support tricky injections. | |
| Feb 1, 2021 at 2:12 | comment | added | Mukus | @SkipSaillors Yes the Controller has to make a choice because the DI container will not allow specifying what service you want to inject. | |
| Jan 28, 2021 at 9:08 | review | Suggested edits | |||
| Jan 28, 2021 at 13:45 | |||||
| Sep 30, 2020 at 13:57 | comment | added | Skip Saillors | I understand this is a workaround. It is not exactly an answer, so I can't up-vote. I won't down-vote because there is a clear notice that this is a workaround. If we are counting on dependency injection to isolate clients of interfaces from knowledge of implementations, this didn't work. The client c'tor has to make a choice. | |
| Sep 20, 2020 at 8:26 | comment | added | user2243747 |
@MiguelA.Arilla It looks like this approach is not working in .net core 3.1 . Below is my sample code and value of fly object is always null ->> var services = new ServiceCollection(); services.AddTransient<IFly,Bird>(); services.AddTransient<IFly,Aeroplane>(); var sp = services.BuildServiceProvider(); var fly = sp.GetService<Aeroplane>();//Not able to resolve Aeroplane. Always null fly.Fly();
|
|
| Apr 11, 2020 at 1:17 | comment | added | IronMan | @MiguelA.Arilla: Can you please explain how to create an object of type "Consumer" or how to do the dependency injection of that class? | |
| Aug 9, 2019 at 12:42 | history | edited | Ian Kemp - SO dead by AI greed | CC BY-SA 4.0 |
moved delegate inline for tidiness
|
| Jul 16, 2019 at 12:26 | history | edited | Miguel A. Arilla | CC BY-SA 4.0 |
Add delegate note
|
| Apr 24, 2019 at 10:34 | comment | added | Piotr Kula | Down vote explanation - Its very interesting but I am currently refactoring a massive code base to remove all this Func magic somebody did a few years ago (before the MS DI revolution) The problem with this is that it dramatically increases the connascence complexity on properties which can cause convoluted DI resolution further down the line. For example I worked on a Windows service handler had over 1.6k lines of code to do with Func and after doing it the recommended way of DI I reduced it to 0.2k lines. OK-Lines of code mean nothing.. except its easier to read and resuse now... | |
| Mar 5, 2019 at 14:25 | history | edited | Miguel A. Arilla | CC BY-SA 4.0 |
Remove underscore notation
|
| Nov 5, 2018 at 11:43 | history | edited | Miguel A. Arilla | CC BY-SA 4.0 |
Registered the Consumer class of the example into the DI container
|
| Sep 28, 2018 at 4:58 | comment | added | Gayan |
i did the same thing but throwing exception Activated Event Time Duration Thread Exception thrown: 'System.ObjectDisposedException' in Microsoft.Extensions.DependencyInjection.dll ("Cannot access a disposed object.") Exception thrown: 'System.ObjectDisposedException' in Microsoft.Extensions.DependencyInjection.dll ("Cannot access a disposed object.") Hyperlink: Activate Historical Debugging 8.97s [428] WorkPool-Session#2:Connection(3a5aaef7-e40f-4607-9d12-eacbd0dd5f6d,amqp://localhost:5672)
|
|
| Aug 30, 2018 at 11:44 | comment | added | Steven Liekens | +1 but I recommend using descriptions as keys. Example: "legacy" for ServiceA, "modern" for ServiceB, "next" for ServiceC. That makes it easier to remove or replace service registrations without having to update all the code that calls the Func. | |
| S Jun 15, 2018 at 14:54 | history | suggested | Oscar André | CC BY-SA 4.0 |
Complete rename from "factory" to "serviceProvider"
|
| Jun 14, 2018 at 20:56 | review | Suggested edits | |||
| S Jun 15, 2018 at 14:54 | |||||
| Jun 1, 2018 at 9:51 | comment | added | Assil | While it seems @Miguel A. Arilla has point it out clearly, I created on top of his useful solution another solution which looks neat but requires alot more work. It definitely depends on the above solution. | |
| Apr 26, 2018 at 16:18 | history | edited | Miguel A. Arilla | CC BY-SA 3.0 |
Improved code readability
|
| S Mar 10, 2018 at 0:21 | history | suggested | VFein | CC BY-SA 3.0 |
fixing mistake, should use field. "serviceAccessor" is not a variable in the instance method of Consumer.
|
| Mar 9, 2018 at 17:19 | review | Suggested edits | |||
| S Mar 10, 2018 at 0:21 | |||||
| Mar 1, 2018 at 19:04 | vote | accept | LP13 | ||
| Feb 13, 2018 at 11:44 | history | edited | Miguel A. Arilla | CC BY-SA 3.0 |
Extended answer
|
| Jan 18, 2018 at 16:42 | comment | added | Miguel A. Arilla | @AnupamSingh In my opinion, most kind of small to medium applications running on .NET Core do not need any DI framework, just adds complexity and unwanted dependencies, the beauty and simplicity of the built-in DI is more than enough, and it can also be extended with ease. | |
| Jan 18, 2018 at 11:47 | comment | added | Anupam Singh | +1 Very neat and clean, because when we use other di-container we have to include their package whenever we need to resolve dependencies, eg. ILifetimeScope in AutoFac. | |
| Oct 27, 2017 at 15:32 | history | edited | Miguel A. Arilla | CC BY-SA 3.0 |
clarify code intention
|
| Aug 10, 2017 at 19:36 | comment | added | Sergey Akopov | Using a factory pattern like this is the best way to go. Thanks for sharing! | |
| Jul 12, 2017 at 21:32 | comment | added | Miguel A. Arilla | @MatthewStevenMonkan updated my answer with an example | |
| Jul 12, 2017 at 21:25 | history | edited | Miguel A. Arilla | CC BY-SA 3.0 |
added 442 characters in body
|
| Jul 12, 2017 at 21:16 | comment | added | Matthew Steven Monkan | How do you retrieve one of the services by string from another class? | |
| Jun 21, 2017 at 12:15 | history | edited | Miguel A. Arilla | CC BY-SA 3.0 |
added 29 characters in body
|
| May 25, 2017 at 10:14 | history | answered | Miguel A. Arilla | CC BY-SA 3.0 |