Skip to content

Using the package

Joshua Hegedus edited this page Nov 5, 2023 · 8 revisions

There are two main ways to use the package.

  • Registering your classes in the same collection that you need for registering this module. (Recommended)
  • Passing the IServiceProvider through the constructor.

Registering your own classes

The advantage of using a Container is that let's say you have a class of which constructor takes 3 parameters:

internal class ExampleService
{
   public ExampleService(ServiceA servicA, SmallService smallService, BigService bigService)
   {
      // Do the assignments
   }
}

NOTE: It is recommended to use interfaces and then register and resolve them with the interface

Now if you register all of your services in the collection and register the ExampleService as well, then you can just call.

var collection = new ServiceCollection();  
// The registrations shoud go here 
var provider = collection.BuildServiceProvider();
var exService = provider.GetRequiredService<ExampleService>();

And everything will be injected for you. For example the Reader from this package:

public Reader(ILogger logger, IWriter writer, IDataParser dataParser)
{
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    _writer = writer ?? throw new ArgumentNullException(nameof(writer));
    _dataParser = dataParser ?? throw new ArgumentNullException(nameof(dataParser));
}

The there parameters are registered in the module of the project:

collection.AddScoped<ILogger, Logger.Logger>(_ => new Logger.Logger(Guid.NewGuid()));
collection.AddScoped<IWriter, Writer>();
collection.AddScoped<IReader, Reader>();
collection.AddScoped<IDataParser, DefaultDataParser>()

Registering in a separate class

You can create a "Module" for your project by creating a new class and implementing the IModule from the joshika39.Core.

Let's say you have a PdfService and a MyLogger class that you want to register. First you need to create a module class:

internal class MyModule : IModule 
{
    public void LoadModules(IServiceCollection collection)
    {
        // Do your class registrations
		
        // Read about lifecycles here: https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines
        collection.AddSingleton<PdfService>();
        collection.AddScoped<MyLogger>();		
    }
}

Then you just have to call your module's LoadModules function:

var collection = new ServiceCollection();  
new CoreModule().LoadModules(collection, "reader-tests"); 
new MyModule().LoadModules(collection);
var provider = collection.BuildServiceProvider();

Registering directly in the composition root

This is a the same if you take out the core of your LoadModules function from to previous example

var collection = new ServiceCollection();  
new CoreModule().LoadModules(collection, "reader-tests"); 

// Do your class registrations	
// Read about lifecycles here: https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines
collection.AddSingleton<PdfService>();
collection.AddScoped<MyLogger>();	

var provider = collection.BuildServiceProvider();

IServiceProvider in the constructor

Basically you only need to create you class and pass the IServiceProvider and then manually resolve the services

internal class ExampleService
{
   private readonly ServiceA _serviceA;
   private readonly SmallService _smallService;
   private readonly BigService _bigService;

   public ExampleService(IServiceProvider serviceProvider)
   {
      _serviceA = serviceProvider.GetRequiredService<ServiceA>();
      _smallService = serviceProvider.GetRequiredService<SmallService>();
      _bigService = serviceProvider.GetRequiredService<BigService>();
   }
}

And this is how to create the object:

var collection = new ServiceCollection();  
new CoreModule().LoadModules(collection, "reader-tests"); 
var provider = collection.BuildServiceProvider();

var exampleService = new ExampleService(provider);

References