1

I have registered the implementation of my logger in ServiceCollection in the start up:

services.AddTransient(typeof(ILogger<>), typeof(GenericLogger<>));

Usually, I do this to inject using Constructor:

class DynamoEventProcessor
{
    private readonly IRepository _repository;
    private readonly IDogStatsd _dogStatsd;
    private readonly ILogger<DynamoEventProcessor> _logger;

    public DynamoEventProcessor(IRepository repository, IDogStatsd dogStatsd, ILogger<DynamoEventProcessor> logger)
    {
        _repository = repository;
        _dogStatsd = dogStatsd;
        _logger = logger;
    }
}

But I have a class where there is no constructor:

public class ProfileContent
{
    public MemoryStream Content { get; set; }
    public string ContentAlgorithm { get; set; }
    public List<Dictionary<string, AttributeValue>> DataKeys { get; set; }
    public long ExpiresUtc { get; set; }
    public long Version { get; set; }
    public long Deleted { get; set; }

    public static Dictionary<string, EncryptedDataAndKeys> GetEncryptedDataAndKeys(Dictionary<string, Dictionary<string, AttributeValue>> profileContentAttributes)
    {
        _logger.LogInformation("Available Keys: " + KeysAsString(keyList));
        _logger.LogInformation("AccountId missing Coporate Data: " + _converter.GetValueFromAttributeValue(attributes["AccountId"]).ToString());
        var encryptedDataAndKeys = new Dictionary<string, EncryptedDataAndKeys>();

        foreach (var item in profileContentAttributes)
        {
            encryptedDataAndKeys.Add(item.Key, GetEncryptedDataAndKey(item.Value));
        }

        return encryptedDataAndKeys;
    }
}

My _logger failed here due to null. I understand the problem, that I didn't inject it properly. How can I inject it when I use it in static method without instantiating an object?

SimonG
  • 304
  • 10
  • 19
Muthaiah PL
  • 896
  • 1
  • 11
  • 23
  • 1
    I would make the static method a service (probably singelton) and register it in the container. An other solution would be, pass the needed service as parameter. If you realy want to go the route you current do, you need an [service locator](https://dotnetcoretutorials.com/2018/05/06/servicelocator-shim-for-net-core/), which is **not recommended**. – Christian Gollhardt May 27 '19 at 23:47
  • Possible duplicate of [How to use DI inside a static Method in Asp.net Core rc1](https://stackoverflow.com/questions/36027206/how-to-use-di-inside-a-static-method-in-asp-net-core-rc1) – Christian Gollhardt May 27 '19 at 23:56

1 Answers1

7

You can't inject into a static constructor. You have a couple of options:

1.) Pass ILogger into the method, hopefully the calling code has it injected.

2.) Have a static property for ILogger on ProfileContent and then in your Startup file, in the Configure method, initialize it i.e.

ProfileContent.Logger = app.ApplicationServices.GetService<ILogger<ProfileContent>>();

then use Logger in your static method. Personally, I would go for option 1.

JohanP
  • 4,790
  • 2
  • 20
  • 30
  • 2
    The only thing I could add to this is: 3) Get rid of the statics, with Singleton registrations in the DI, do this class really need to be static? – Robert Perry May 28 '19 at 11:38
  • 1
    You preferred option 1. Option 2. was hugely less code for me. What's the reason for preferring option 1.? – Bob Koury Jul 06 '21 at 20:25
  • 1
    Option 2 is the service locator anti pattern. It also blackboxes the creation and assignment of Logger and as a general rule, I'm not a fan of static properties. – JohanP Jul 06 '21 at 23:39