9

I'm trying to figure out how best to implement extension methods that register services when users of my library may want to override some of the default implementations of various interfaces. It seems like there are 2 ways of doing things.

The first way is to use services.TryAdd inside the extension method, which would enable you to register the override implementation by using services.Add before calling the main extension method so that your implementation gets there first. This works because .TryAdd won't add if there is already something registered for the interface.

If the extension method uses plain old services.Add instead of .TryAdd then you can still override the implementation but now you have to register your implementation after calling the main extension method that adds the default implementation.

To me it seems the first approach is the better one. If you call services.Add more than once with a different implementation of the interface then they both do get registered and you could actually take a dependency on an IEnumerable of the interface to get all of them. But if you really only need one implementation in the app then it seems better not to have any extra implementations in the collection. Obviously if the app does use multiple implementations of the interface then you would want to add all the ones you need.

I wonder if there is a consensus about this or a recommendation or is it just up to individual taste.

Joe Audette
  • 35,330
  • 11
  • 106
  • 99
  • 1
    The first one is better and what most middlewares use right now, i.e. how Mvc middleware registers it's dependencies: https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs – Tseng May 08 '16 at 16:03
  • that is what I think too and it will work no matter if the user registers a custom version before or after, but you still get 2 if registered after. I guess what made me question it is I needed to override IAntiForgeryTokenStore and I was told to by someone smart to make sure I register it after .AddMvc, and that worked though I have not tried to see if it also works registering before – Joe Audette May 08 '16 at 16:20
  • I see now it does work if I register before calling .AddMvc, I should have tested that before and I would not have asked this question, but the person who told to do that on jabbr had just helped me solve something I was struggling with for a few days so I guessed he was right and I had missed something conceptually. I think someone else had also told me I need to register my custom viewengine after mvc but that also seems fine doing it first – Joe Audette May 08 '16 at 17:15
  • 1
    one additional question, is it also considered best to put IServiceCollection extensions in the Microsoft.Extensions.DependencyInjection namespace? – Joe Audette May 08 '16 at 17:25
  • 1
    I'd say yes, all of the asp.net project does so too. It has the benefit that you don't need to import a namespace (`Microsoft.Extensions.DependencyInjection` is always there for `IServiceCollection` anyway) for the `UseXXX` and `AddXXX` methods and will always get all of the registration methods once you referenced a package in your project.json – Tseng May 08 '16 at 19:41
  • I'd say no, unless you are writing libraries for Microsoft. It has the downside of being very difficult to find without intellisense. A new developer (to a project) has to have a solid knowledge of all of the dependencies to know how to find the extension code (see [Eric Lippert's answer](https://stackoverflow.com/questions/5915033/use-of-namespaces-in-c-sharp)). If they are namespaced like the rest of their library/assembly, the `using` will be very helpful in tracing the code. – user01CU812 Jun 27 '19 at 02:10
  • You don't have to be Microsoft to ship nuget packages, and it is more friendly for consumers of nugets if they don't have to add using mynamespace in order to get my IServiceCollection extensions to show up in intellisense when they type services. – Joe Audette Jun 27 '19 at 12:09
  • 2
    @JoeAudette Microsoft recommends putting extensions in the Microsoft.Extensions.DependencyInjection namespace here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2#code-try-5 – Chris R. Donnelly Sep 03 '19 at 23:48
  • 2
    @ChrisR.Donnelly And yet they give the exact opposite guidance [here](https://learn.microsoft.com/en-us/dotnet/core/extensions/options-library-authors#namespace-guidance). (I know your comment is old but they haven't changed the doc you linked to, so they really seem to be contradicting themselves.) Personally, I'd never use an MS namespace for my own stuff. That feels wrong to me. – Todd Menier Jul 27 '22 at 20:05

0 Answers0