C# – Should .NET Core class libraries register their own implementations

.net coreasp.net-corecdependency-injectionioc-containers

Our team had recently a big struggle of deciding whether it is a good practice or not for the .NET Core class libraries to register their own implementations by the fact of providing a IServiceCollection extension methods like AddMyServices().

My point was that it is good to do this because:

  • Top level application does not need to know all the details of the
    underlying library it is going to use,
  • Top level application (usually Startup class) is not polluted with references to all the namespaces required to register its implementation.
  • If top level application
    wants to provide its own custom implementation of some interfaces
    defined in the referenced library, it still can do it. .NET Core
    dependency injection allows multiple registrations.
  • If there is more applications referencing this class library, you would not need to copy paste a block of e.g. AddTransient lines to each application.

Counterarguments were that:

  • Some example applications use the approach of registering all the
    implementations in the top level Startup method.
  • The above approach is only used for features (but it creates semantic doubts around what can be called a feature and what not). Still class library can name
    features it implements and provide separate AddFeatureXYZ() methods
    in the IServiceCollection extension class.
  • Using AddService() extension method which registers all the implementations it may provide, may impact the performance of DI container, which makes
    sense in case where certain class library provide many impementations
    but only few are used. But a developer still have a freedom of
    calling AddServices() or not.

I wanted to ask about it more experienced .NET Core developers about their approaches with all the pros, which maybe I am missing. If there are any strong arguments for using the second approach I didn't list here, I would really love to get acquainted with it.

PS. This question was moved from StackOverflow as it was marked as more opinion based. In my opinion it is touching the core priciples of object oriented programming, and the question is not to find out what majority of developers is choosing, but about why somebody favours one approach against the other.

Thanks,
Radek

Best Answer

The ASP.Net core docs recommend it

Each services.Add{SERVICE_NAME} extension method adds (and potentially configures) services. For example, services.AddMvc() adds the services Razor Pages and MVC require. We recommended that apps follow this convention. Place extension methods in the Microsoft.Extensions.DependencyInjection namespace to encapsulate groups of service registrations.

But I don't.

One of the most annoying things about configuring plugins is trying to guess the extension method to use to configure them. Or I should say, the version that you have of them as the name seems to change between versions and frameworks

Secondly, often these rolled up registration methods don't expose all the things you might want to override or configure on the underlying services. The whole point of the service manager is so you can replace out dependencies when required, but the extension method doing it for you can prevent that.

But perhaps most importantly, I don't think that this convention has taken hold yet. There seem to be some competing philosophies when it comes to startup.cs and program.cs. If you only support one method you are going to be on someone's wrong side.

I would provide the extension method, but in a separate optional package. Allow users to manually register the components if they want or use the extension method for a default setup.

Related Topic