0

I have the following problem:

I have a class, where I inject Logger via DI.

But at the end I want to instantiate this class.

Here is the code:

public class DokumentInhaltJson : SimpleValueObject<string>
{
    public readonly ILogger<DokumentInhaltJson> _logger;
    
    private DokumentInhaltJson(
        string value, ILogger<DokumentInhaltJson> logger) : base(value)
    {
        _logger = logger;
    }

    public static Result<DokumentInhaltJson> Create(string value)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return Result.Failure<DokumentInhaltJson>("Error message 1");
        }

        try
        {
           JObject objectToValidate = JObject.Parse(value);
        }
        catch (Exception e)
        {
            return Result.Failure<DokumentInhaltJson>("Error message 2"));
        }

        return Result.Success(new DokumentInhaltJson(value));
    }
}

The problem now is that new DokumentInhaltJson now wants the logger as a second parameter.

What can I do here?

Steven
  • 166,672
  • 24
  • 332
  • 435
Julia
  • 19
  • 1
  • Which class do you want to instanciate? – Haytam Nov 11 '20 at 21:17
  • 2
    This looks more like it should be a DTO and those types should not rely on DI or have behavior. – Igor Nov 11 '20 at 21:18
  • 1
    What Igor said. – TheGeneral Nov 11 '20 at 21:20
  • Yes, it is a DTO, nevertheless I want to log here in case of an error. – Julia Nov 11 '20 at 21:21
  • What logging framework are you using? Is this log4net or nlog? If so I would recommend not injecting those and just making a static field reference in the type. Chances that you will be replacing that with other logging frameworks is slim to none so there is no clear advantage to using DI for that. – Igor Nov 11 '20 at 21:21
  • 1
    A DTO shouldn't be doing things like parsing JSON (it should be format-agnostic - any parsing should be done by the layer which receives/retrieves the JSON text), so there'd be no need for error handling or logging like you've shown. So again, what Igor said – ADyson Nov 11 '20 at 21:23
  • If you are using Dependency Injection you will never call `new DokumentInhaltJson(...)` you will use `container.Resolve()` instead, which will take care of instantiating the logger. See e.g. https://stackoverflow.com/a/32461714/1333247 – Jakub Fojtik Nov 11 '20 at 21:24
  • Microsoft.Extensions.Logging – Julia Nov 11 '20 at 21:24
  • 1
    You would have to use a service locator pattern, which is generally considered an anti-pattern, to get a logger instance and pass it along with the value to the constructor. Again, this is something I would not advise. Try to rethink the design instead (I am not the only one who is thinking this based on the comments). – Igor Nov 11 '20 at 21:29
  • Thanks for your answers, Igor! Do you have an example for this service locator pattern. I am not sure what you mean. – Julia Nov 11 '20 at 21:31
  • 2
    When you see `static` and DI together, there's almost always something very odd that needs rethinking. It doesn't make any sense either to have a DTO in a DI container, DI is for services not for data classes – Camilo Terevinto Nov 11 '20 at 21:31
  • 1
    @Julia please be clear that Igor's point was **not** to use the service locator idea (hence the words _"this is something I would not advise"_ in the comment). Do you understand what an "anti-pattern" is? – ADyson Nov 11 '20 at 21:33

1 Answers1

1

I believe you are attempting to combine an object factory within the type you are creating. Move your factory to it's own type and use that to create instances of DokumentInhaltJson.

public class DokumentInhaltJson : SimpleValueObject<string>
{
    private string _value;

    public DokumentInhaltJson(string value)
    {
        _value = value;
    }
}

public class DokumentInhaltJsonFactory
{
    private readonly ILogger _logger;

    public DokumentInhaltJsonFactory(ILogger logger)
    {
        _logger = logger;
    }

    public Result<DokumentInhaltJson> Create(string value)
    {

        if (string.IsNullOrWhiteSpace(value))
        {
            _logger.LogError("Null");
            return Result.Failure<DokumentInhaltJson>(string.Format(ErrorMessages.Common_FeldDarfNichtLeerSein,
                                                                nameof(DokumentInhaltJson)));
        }

        try
        {
            JObject objectToValidate = JObject.Parse(value);
        }
        catch (Exception e)
        {
            _logger.LogError(e.Message);
            return Result.Failure<DokumentInhaltJson>(string.Format(ErrorMessages.Common_MussGueltigesJSONObjektSein,
                                                                nameof(DokumentInhaltJson)));
        }

        return Result.Success(new DokumentInhaltJson(value));
    }
}
Jerry
  • 1,477
  • 7
  • 14