3

I'm refactoring an ASP.Net Core 2.2 webapp. I decided to move some functionality into a separate class library (.net core 2.2) project. The class library has a dependency on System.IO.Abstractions (so it can be unit-tested). A simplified version of the class library looks like this:

using System; using System.IO.Abstractions; namespace ClassLibrary1 { public class TestService { private IFileSystem fileSystem; internal TestService(IFileSystem fileSystem) { this.fileSystem = fileSystem; } public TestService() : this(new FileSystem()) {} } } 

In the web application project I've added a reference to the class library dll. In Startup.cs I've added the using statement, and in ConfigureServices I'm registering the TestService (defined in the class Library) with the DI container:

 ... using ClassLibrary1; namespace WebApplication1 { public class Startup { ... public void ConfigureServices(IServiceCollection services) { ... services.AddScoped<TestService>(); } ... } } 

I'm trying to instantiate the service in the controller, like so:

using ClassLibrary1; namespace WebApplication1.Controllers { public class HomeController : Controller { TestService service; public HomeController(TestService service) { this.service = service; } ... } } 

When I run this project I get the following error:

FileNotFoundException: Could not load file or assembly 'System.IO.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=96bf224d23c43e59'. The system cannot find the file specified.

How do I resolve this without adding the System.IO.Abstractions package to the webapp project ?

My understanding is that the problem arises because the constructor of the class I'm trying to resolve using DI contains the IFileSystem type which is an external dependency, so the webapp cannot resolve it.

One thing I've tried to do after looking around for a solution to this problem is to add an extension method to the class library, which takes care of registering needed dependencies:

using Microsoft.Extensions.DependencyInjection; using System.IO.Abstractions; namespace ClassLibrary1 { public static class IServiceCollectionExtension { public static IServiceCollection AddTestService(this IServiceCollection services) { services.AddScoped<IFileSystem, FileSystem>(); services.AddScoped<TestService>(); return services; } } } 

Then use this extension method in the ConfigureServices of the webapp like this:

services.AddTestService(); 

However this results in the same error message.

EDIT:

The real question I have is how to properly author the class library so it can be used without having to worry about dependencies ?

So in the webapp the TestService should be instantiated using the public parameterless constructor, and inside the classlib solution in a xunit project the TestService can be instantiated using the internal constructor.

1
  • 1
    try creating the class library using .net standard 2.0. As per this table, .net core 2.2. supports upto .net standard 2.0 Commented Oct 21, 2019 at 13:19

1 Answer 1

4

You should not resolve dependencies in your class library. The composition root can only be in the main application. Composition root is the start and earliest point in an application lifecycle where object graph can be set up.

So Startup.cs is the composition root in ASP.NET Core application.

services.AddScoped<IFileSystem, FileSystem>(); 

Class libraries don't have a composition root.

Sign up to request clarification or add additional context in comments.

2 Comments

So how would others use this class library within my organization for example ? They need to know the dependencies of the class library up front and resolve them. Maybe the question wasn't clear - I'm not trying to make the provided code example work, I'm looking for information how to properly author the class library so others can use it without having to worry about dependencies. I've updated the question to make it clearer.
@GeorgiRangelov you can't use class library them without an application and the IoC Container used is a choice of the application not of the library.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.