Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Core 2, DI, configuration file

I am studying .NET Core 2 and I don't like how DI is managed... on the web I read something like the following steps:

  1. creating an interface like IService

  2. creating an implementation for IService

  3. adding it on the scope of .NET Core container into Startup.Configuration method resolving the dependency.

  4. finally I can use it into the constructor of my custom controller.

In .NET classic I used a dedicated XML configuration file to manage dependencies: can I use a configuration file (JSON or XML are the same) to do the same I would have to do into Startup.Configuration method?

...otherwise someone can explain me the reason why configure the services into Startup.Configuration is the better way?

Thanks so much...

like image 696
Lollo Avatar asked Dec 03 '22 19:12

Lollo


1 Answers

First, to answer your question "can I use a configuration file", the answer is emphatically "yes". Why shouldn't you is answered later, but for now, here's a poor man's version of how you might do this by adding to your appsettings.json file. Note that this code is not optimal, but is designed to show you how you could implement this solution.

Let's start with some classes to hold the data:

public class ServicesConfiguration
{
    public IEnumerable<ServiceItem> Singleton { get; set; }
    public IEnumerable<ServiceItem> Transient { get; set; }
}

public class ServiceItem
{
    public string Service { get; set; }
    public string Implementation { get; set; }
}

Now add a section to your JSON file, you may even want to keep this file external to the main config, but that's an implementation detail I will leave up to you:

{
    //snip main config....

    "Services" : {
        "Singleton": [
            { 
                "Service": "YourNamespace.IFoo1, YourNamespace", 
                "Implementation": "YourNamespace.Foo1, YourNamespace" 
            },   
            {
                "Service": "YourNamespace.IFoo2, YourNamespace", 
                "Implementation": "YourNamespace.Foo2, YourNamespace" 
            }  
        ],
        "Transient": [
            {
                "Service": "YourNamespace.IBar1, YourNamespace",
                "Implementation": "YourNamespace.Bar1, YourNamespace"
            }    
        ]
    }
}

And now an extension method to configure it all:

public static IServiceCollection AddFromConfigurationFile(this IServiceCollection services, 
    IConfigurationSection configuration)
{
    var servicesConfiguration = configuration.Get<ServicesConfiguration>();

    foreach(var service in servicesConfiguration.Singleton)
    {
        services.AddSingleton(Type.GetType(service.Service), Type.GetType(service.Implementation));
    }

    foreach(var service in servicesConfiguration.Transient)
    {
        services.AddTransient(Type.GetType(service.Service), Type.GetType(service.Implementation));
    }

    //Other scopes here...

    return services;
}

And call it in ConifigureServices like this:

services.AddFromConfigurationFile(Configuration.GetSection("Services"));

So, nice and simple right? Why shouldn't you do this? A few ideas off the top of my head:

  1. Why change how almost all DI implementations work? If it ain't broke, why fix it? Just because you are used to a particular method, doesn't mean it's a good idea.
  2. Type safety: You lose compile time checking of the types you specify in the configuration file.
  3. Security: Having this in a config file would let someone change the implementation to a class of their own choice.

I'm sure there are more, but... it's your app!

like image 76
DavidG Avatar answered Dec 11 '22 04:12

DavidG