Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DI using dynamic constructor injection

I have a problem using DI with constructor properties. I am building a PDFBuilder based on my IPDFBuilder.

public interface IPDFBuilder
{
    string templatefilepath { get; }
    string templatefilename { get; }
    Dictionary<string, string> dict { get; }    
    void CreatePDF();
}

public class PDFBuilder : IPDFBuilder
{
    public string templatefilename { get; private set; }
    public string templatefilepath { get; private set; }
    public Dictionary<string, string> dict { get; private set; }

    public PDFBuilder(string templatefilename, string templatefilepath, Dictionary<string, string> dict)
    {
        this.templatefilename = templatefilename;
        this.templatefilepath = templatefilepath;
        this.dict = dict;
    }

    public void CreatePDF() {
        //Do something
    }
}

This PDFBuilder can and will be used in multiple controllers, for example:

public class KeuringController : Controller
{
    private IPDFBuilder _PDFBuilder;
    public KeuringController(IPDFBuilder pdfBuilder)
    {
        _PDFBuilder = pdfBuilder;
    }
    //Action methods that use `PDFBuilder` below...
}

However, I can't set the properties of PDFBuilder in the startup class (where DI registration is beeing done) because different controllers will use different values for the properties of the PDFBuilder class. 1 simple solution would be to just make the setters of the properties public so in an action method I can set the values and then call CreatePDF(). However this doesn't feel right. Another simple solution would be to remove the class properties and just pass the 3 properties of PDFBuilder as method properties to the CreatePDF method like this:

public void CreatePDF(string templatefilename, string templatefilepath, Dictionary<string, string> dict) {
        //Do something
    }

But now let's say that my PDFBuilder whould have 10 methods which all need these 3 properties. Then this is not the correct solution right?

What would be the correct solution then? I have encountered this problem multiple times with different classes/interfaces implementations and would like to have some help with designing in these situations.

like image 433
Kip ei Avatar asked May 07 '26 06:05

Kip ei


1 Answers

You are injecting runtime data into your component's constructor, which is a bad thing. The solution is to move those runtime values out of the constructor into the CreatePDF method:

public interface IPDFBuilder
{
    void CreatePDF(string templatefilepath, string templatefilename,
        Dictionary<string, string> dict);
}
like image 108
Steven Avatar answered May 12 '26 09:05

Steven



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!