16

I want to rebuild a .NET Framework library to .NET Core, and then use this library in the .NET Framework app.

The library needs a database connectionstring. In .NET Core I would use Dependency Injection to pass the configuration with the connectionstring to the library class.

public MyRepository(IConfiguration config)
{
    _connectionString = config.GetConnectionString("MyDb");
}

But how can I use this class from the .NET Framework 4.6 library without introducing complex DI frameworks?

fantastischIdee
  • 465
  • 2
  • 6
  • 17

2 Answers2

27

I'm already using the new Microsoft.Extensions libraries in .NET Framework 4.7.1, mainly the DependencyInjection and Configuration libraries.

The 2.x libraries are compatible with .NET Standard 2.0, which means they can be added to applications that target any runtime that is compatible with .NET Standard 2.0, ie .NET Framework 4.7.1 and above or .NET Core 2.0 and above.

In older runtimes (4.6.1 and later), NuGet may have to add some extra packages with newer versions of some system assemblies, eg System.Runtime.

You can't add the 2.0 Extension packages to 4.6 at all. You can add the older, 1.x versions which are use in .NET Core 1.x.

Configuring the extensions is done in the same way in .NET Core and Full Framework:

  1. You create a ConfigurationBuilder, add configuration providers and call Build() in the end to get an IConfigurationRoot object:

    IConfigurationRoot configRoot = new ConfigurationBuilder()
        .AddUserSecrets<Program>()
        .AddJsonFile($"appsettings.json")
        .Build();
    
  2. Create a ServiceCollection, register services and call BuildServiceProvider() to get a ServiceProvider. You'll use that ServiceProvider to create instances of classes that require injection.

ASP.NET Core, which also works on the Full framework provides extra helper libraries that hide the boilerplate code.

IServiceCollection services = new ServiceCollection();
ServiceProvider provider= services.AddSingleton<MyService>()
                                  .AddTransient<AnotherService>()
                                  .AddTransient<ServiceThatNeedsTheOthers>()
                                  .BuildServiceProvider();

Assuming the third service is :

public class ServiceThatNeedsTheOthers
{
    public ServiceThatNeedsTheOthers(MyService s1,AnotherService s2){..}
}

You can create it with :

var service3=provider.GetRequiredService<ServiceThatNeedsTheOthers>();

All this is described in Mark Michaelis' Essential .NET column in MSDN Magazine, eg Dependency Injection with .NET Core and Configuration in .NET Core. The articles show how to setup and use the Extensions in Console applications where you need to write all the boilerplate.

PS ASP.NET Core 2.0 can target the Full framework too. For a new web application it may make sense to create an ASP.NET Core 2.0 project targeting 4.7.1

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • Removed the 4.6 version of the .NET Framework, as I'm interested in how to do this in the .NET Framework that is compatible with dotnet standard – fantastischIdee Mar 30 '18 at 11:53
  • Then use 4.7.1. It's Standard 2.0-compatible so it doesn't need any extra libraries – Panagiotis Kanavos Mar 30 '18 at 11:59
  • @fantastischIdee PS ASP.NET Core 2.0 can also target the full framework, not just Core. If you want to create a web application you should probably create an ASP.NET Core 2.0 project – Panagiotis Kanavos Mar 30 '18 at 12:01
  • @PanagiotisKanavos I interpreted the question to mean he wants to create a `.netstandard20` library that uses DI that will be referenced by a .NET Framework application. There is no mention of building a web app. – McGuireV10 Mar 30 '18 at 12:13
  • @McGuireV10 even in .NET Core console apps you have to know how to configure tthe built-in DI. Most examples are about ASP.NET Core which hides the setup steps behind `WebHost.CreateDefaultBuilder`. – Panagiotis Kanavos Mar 30 '18 at 12:21
  • Obviously. This is why I asked if the OP was familiar with the concept of composition root. The answer would change how I presented sample code. But I suppose he can glean it from the articles you linked. – McGuireV10 Mar 31 '18 at 11:16
  • Where does this code go? Do I put the `ConfigurationBuilder` and `IServiceCollection ` in the Global.asax.cs? – Don Rhummy Apr 05 '19 at 23:50
  • @PanagiotisKanavos re PS. As of Core v3.0, you can no longer target the Full Framework (https://devblogs.microsoft.com/aspnet/a-first-look-at-changes-coming-in-asp-net-core-3-0/). Hopefully this will help anyone else trying to use the latest Core code with the Full Framework. If you're happy with Core v2.* then it's fine. – sixeyes Apr 22 '20 at 18:50
  • @PanagiotisKanavos how can I add the DI for ILogger with log4net in standard net framework ? – fededim Mar 31 '21 at 15:41
  • 1
    Easy as a piece of cake. You must add the same net core package Microsoft.Extensions.Logging.Log4Net.AspNetCore and use `services.AddLogging(opt => opt.AddLog4Net("log4net.config"))`, thank you very much for your answer. – fededim Mar 31 '21 at 16:23
1

The scenario you describe is what .NET Standard is meant to achieve. Only a class library project can target .netstandard and any such library is compatible with most recent .NET Framework applications as well as .NET Core applications.

The .NET Core assemblies in Microsoft.Extensions.DependencyInjection and Microsoft.Extensions.Configuration are also .netstandard-compatible, which means you can use those in your library and in your applications.

So, yes, you can use .NET Core DI with .NET Framework, and in a library scenario just stick to .NET Standard APIs and it will also work with all .NET implementations. I have some very large, very complicated .netstandard20 libraries which I use with applications targeting both frameworks, and I rarely need to ask myself whether a given API is compatible because the coverage is so good now, but you can find the complete list here.

McGuireV10
  • 9,572
  • 5
  • 48
  • 64
  • Yes, I understand what .NET Standard is meant to achieve. But I'm interested in how to setup my .NET Framework application to have the IConfiguration available for DI in MyRepository. In .NET Core this is done for me by WebHost.CreateDefaultBuilder... – fantastischIdee Mar 30 '18 at 11:38
  • Are you familiar with the DI concept of a composition root? Basically the application is responsible for registering DI services, then constructor DI in your library "just works" automatically. (If your library also needs to register DI services, add a service registration extension to the library and call that from the application during startup.) If you aren't familiar I can open another answer to demonstrate. – McGuireV10 Mar 30 '18 at 11:46
  • 1
    @fantastischIdee 4.6 no go. 4.6.1 possible, just add the packages. *Configuring* the packages for console/non-Core applications is another matter though – Panagiotis Kanavos Mar 30 '18 at 11:47
  • @McGuireV10 You can't just add any DI library without *configuring* it. ASP.NET Core provides helpers to do that that aren't available even in .NET Core console applications. This isn't a question about DI in general – Panagiotis Kanavos Mar 30 '18 at 11:49
  • 1
    @PanagiotisKanavos I have six .NET Core utility console programs that stand up a very complex DI-dependent library every 5 minutes 24/7, and the same library also works in .NET Framework Azure web sites. Not really sure what you're trying to say but .NET Core DI is simple to use without ASP.NET Core. – McGuireV10 Mar 30 '18 at 11:51
  • Removed the 4.6 version of the .NET Framework, as I'm interested in how to do this in the .NET Framework that is compatible with dotnet standard – fantastischIdee Mar 30 '18 at 11:54