Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining DI with constructor parameters?

How do I combine constructor injection with "manual" constructor parameters? ie.

public class SomeObject {     public SomeObject(IService service, float someValue)     {     } } 

Where IService should be resolved/injected by my DI container, and someValue should be specified. How do I mix the two?

like image 606
George R Avatar asked Aug 04 '11 03:08

George R


People also ask

Can you inject dependency through private constructor?

To answer your question, there is no way. by definition, private constructors are inaccessible by other classes.

How do you pass parameters to a constructor?

You can only define the coursebookname variable one time (which is when you specify the type). Remove the String designation from before the variable name when you pass it to the Person constructor and it should work fine. Person p1 = new Person(cousebookname); Spelling aside.

How do I register a class in dependency injection?

For registering the interface and classes, you need to go in the Program class (As Startup class is no more with . NET 6) and use these methods i.e "AddScoped" || "AddTransient" || "AddSingleton" as it defines the lifetime of the services. STEP 5 - Go to Program class and register it.

Can a constructor have a parameter list?

Constructors initialize the attributes in newly created objects. They have the same name as the class. A constructor signature is the constructor name followed by the parameter list which is a list of the types of the parameters and the variable names used to refer to them in the constructor.


2 Answers

Such constructs should be avoided whenever possible. Therefore, ask yourself: is this parameter really required as constructor argument? Or can SomeObject be replaced by a stateless one which is reused by everyone that depends on it by passing the parameter to the method you execute on the object?

e.g. Instead of

public class SomeObject {     private float someValue     public SomeObject(IService service, float someValue)     {         this.someValue = someValue     }      public float Do(float x)     {         return this.Service.Get(this.someValue) * x;     } } 

use

public class SomeObject {     public SomeObject(IService service)     {     }      public float Do(float x, float someValue)     {         return this.Service.Get(someValue) * x;     } } 

If it is required go for a factory:

public interface ISomeObjectFactory {     ISomeObject CreateSomeObject(float someValue); }  public class SomeObjectFactory : ISomeObjectFactory {     private IKernel kernel;     public SomeObjectFactory(IKernel kernel)      {         this.Kernel = kernel;     }      public ISomeObject Create(float someValue)     {         return this.kernel.Get<ISomeObject>(WithConstructorArgument("someValue", someValue);     } } 

Preview: Ninject 2.4 won't require the implementation anymore but allow

kernel.Bind<ISomeObjectFactory>().ToFactory();  // or maybe .AsFactory(); 
like image 154
Remo Gloor Avatar answered Oct 01 '22 23:10

Remo Gloor


You really shouldn't try to use D.I. for this. You could come up with all types of wacky solutions, but they may not make sense down the road.

Our approach is to create a factory via D.I., and the factory's Create method would then build itself out using the passed in D.I. container. We don't have to use this pattern often, but when we do it actually makes the product much cleaner (since it makes our dependency graphs smaller).

like image 45
Beep beep Avatar answered Oct 01 '22 23:10

Beep beep