1

I'm creating a service that requires some config parameters and a logger. Here is the constructor for my service:

public StorageProvider(string directory, ILogger<StorageProvider> logger)

I just added the logger. I used to initalize it like this in my startup.cs:

services.AddSingleton<IStorageProvider>(
    new StorageProvider(Configuration["TempStorage.Path"]));

The directory parameter comes from the config file, and the logger gets DI'ed. How do I setup my IStorageProvider?

7
  • How did you register the ILogger? Is that also a singleton? If so, pass that same instance to the ILogger registration to the StorageProvider construction. Commented Oct 23, 2017 at 19:13
  • The logger get included when you do this: WebHost.CreateDefaultBuilder(args) (see learn.microsoft.com/en-us/aspnet/core/fundamentals/…) Commented Oct 23, 2017 at 19:22
  • 2
    You could use IOptions<StorageProviderOptions> to inject the directory path. Commented Oct 23, 2017 at 19:39
  • Read up on using configurations in documentation learn.microsoft.com/en-us/aspnet/core/fundamentals/… Commented Oct 23, 2017 at 19:44
  • I'm not sure if I'm understanding you exactly, but just to be clear: ILogger<StorageProvider> does not need an actual instance of StorageProvider, if that's what you're thinking. The type param is for distinguishing log entries, it doesn't actually do anything with it. Commented Oct 23, 2017 at 21:06

2 Answers 2

2

You should do the following:

  • Wrap the configuration value TempStorage:Path into its own configuration class, e.g. StorageProviderSettings.
  • Let StorageProvider depend upon that new configuration class.
  • Register that configuration class as singleton into the ASP.NET configuration system.

Example:

public sealed class StorageProviderSettings
{
    public readonly string TempStoragePath;

    public StorageProviderSettings(string tempStoragePath)
    {
        if (string.IsNullOrWhiteSpace(tempStoragePath))
            throw new ArgumentException(nameof(tempStoragePath));
        this.TempStoragePath = tempStoragePath;
    }
}

public sealed class StorageProvider : IStorageProvider
{
    public StorageProvider(
        StorageProviderSettings settings, ILogger<StorageProvider> logger)
    {
        // ...
    }
}

// Registration
services.AddSingleton(new StorageProviderSettings(Configuration["TempStorage.Path"]));
services.AddSingleton<IStorageProvider, StorageProvider>();
Sign up to request clarification or add additional context in comments.

Comments

0

Use the Options pattern as Tratcher suggests in a comment. Read more in the official docs on Configuration.

Basically you define a class to be hold the value you need:

public class StorageProviderOptions
{
    public string TempStoragePath { get; set; }
}

Then in ConfigureServices you register the type:

services.Configure<StorageProviderOptions>();

In your code, you request IOptions<StorageProviderOptions> and set this to an instance of StorageProviderOptions:

public class SomeController
{
    private readonly StorageProviderOptions _options;

    public SomeController(IOptions<StorageProviderOptions> options)
    {
        _options = options.Value;
    }
}

Finally, make sure you have an element in your configuration source that matches the TempStoragePath name. Alternately, you can register the option in ConfigureServices using code:

services.Configure<ServiceProviderOptions>(o => o.TempStoragePath = "temp");

4 Comments

As explained here the injection of IOptions<T> into application components is a bad idea.
Interesting - I had not read that. Having done so, I'm inclined to agree with that article's assessment (though for now IOptions<T> remains the documented MSFT solution to this problem).
but as we all know, the fact that Microsoft documents something (or even builds something) doesn't make it immediately a good solution :)
Indeed, that's true. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.