Thomas
Thomas

Reputation: 1563

Ninject dynamically constructor parameters

In a WebApi project I have a class SyncProductsHelper. This class has two properties, a constructor and some methods:

public class SyncProductsHelper
{
    public int iId { get; set; }
    public string sId { get; set; }

    public SyncProductsHelper(int iId, string sId)
    {
        this.iId = iId;
        this.sId = sId;;
    }

    public ind ChangeSomething(int a)
    {
        iId = a;
    }
}

Now I'm trying to enable DI in my project, so I've installed Ninject and set it up. I write an interface ISyncProductsHelper:

public interface ISyncProductsHelper
{
    void ChangeSomething(int a);
}

And do the binding in my resolver:

_kernel.Bind<ISyncProductsHelper>().To<SyncProductsHelper>();

In my controller which uses this SyncProductsHelper, I setup a constructor and a field:

private readonly ISyncProductsHelper _syncHelper;
public SyncProductController(ISyncProductsHelper syncHelper)
{
    this._syncHelper = syncHelper;
}

The problem is, that I don't know where to set the iId and sId parameters which my current implementation of ISyncProductsHelper needs. They are provided dynamically by the user to the ApiController through a Post, so apparently I cannot use WithConstructorArgument as I've seen elsewhere. The paramters are essential to the class, but should I instead just set them with setter-methods - or what to do.

Upvotes: 3

Views: 2119

Answers (1)

Jim Skerritt
Jim Skerritt

Reputation: 4596

Ninject can't resolve the dependencies iId and sId because they are not available to be bound until your API method is called, but by then it's too late in the binding chain. When you receive a post to the method, an instance of SyncProductController is instantiated and then Ninject attempts to instantiate a SyncProductsHelper, but it can't because it doesn't know where or how to find its dependencies at that point.

I would suggest one of two options:

  1. Refactor your implementation to make SyncProductsHelper act on iId and sId in some other way that would allow you to have a parameterless constructor. Perhaps creating a new class representing iId and sId that it acts on as another parameter for ChangeSomething. Does SyncProductsHelper need to remember the state of these fields?

  2. Consider not using dependency injection at all for this particular class. From your code it looks like SyncProductsHelper is purely just working with primitives, so you could simply create a new instance from your Web API methods directly. You can still easily unit test this class because it doesn't have any external dependencies of its own.

Upvotes: 4

Related Questions