Deploying conditional dependency injection using ninject and C # .net

I am trying to learn the basics of dependency injection (DI). To this end, I conducted a tutorial that demonstrates how to use Ninject for DI by creating a C # console application.

The application essentially seeks to be able to calculate the cost of goods in a shopping cart using various calculation methods.

Classes in the application:

  • Simple product model
  • two classes of shopping carts that act as simple wrappers around a collection of products.
  • The ValueCalculator interface, which requires the ValueProducts method, which returns a certain number of items in carts.
  • Two separate implementations of the ValueCalculator interface (iterative and LINQ approaches)

I tried using conditional injection through the .WhenInjectedTo extension method so that the ShoppingCart object gets a LinqValueCalculator and the ShoppingCartTwo object gets an injectable IterativeValueCalulator. However, in both cases, a LinqValueCalculator is introduced.

See code below

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Ninject; namespace NinjectDemo { // a simple product model public class Product { public int ProductID { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal Price { get; set; } public string Category { set; get; } } // calculator interface public interface IValueCalculator { decimal ValueProducts(params Product[] products); } // a specific implementation of the IValueCalculator using LINQ public class LinqValueCalculator : IValueCalculator { public LinqValueCalculator() {} public decimal ValueProducts(params Product[] products) { return (products.Sum(p => p.Price)); } } // another implementation of IValueCalculator using iteration // (*2 is to so that it returns a different result to LinqValueCalculator) public class IterativeValueCalculator : IValueCalculator { public IterativeValueCalculator() {} public decimal ValueProducts(params Product[] products) { decimal totalValue = 0; foreach (Product p in products) { totalValue += (p.Price) * 2; } return totalValue; } } // a shopping cart modelling a collection of products public class ShoppingCart { protected IValueCalculator calculator; protected Product[] products; public ShoppingCart(IValueCalculator calcParam) { calculator = calcParam; // define the set of products to sum products = new [] { new Product() { Name = "Kayak", Price = 275M}, new Product() { Name = "Lifejacket", Price = 48.95M}, new Product() { Name = "Soccer ball", Price = 19.50M}, new Product() { Name = "Stadium", Price = 79500M} }; } public virtual decimal CalculateStockValue() { // calculate the total value of the products decimal totalValue = calculator.ValueProducts(products); // return the result return totalValue; } } // another, different, shopping cart public class ShoppingCartTwo { protected IValueCalculator calculator; protected Product[] products; public ShoppingCartTwo(IValueCalculator calcParam) { calculator = calcParam; // define the set of products to sum products = new[] { new Product() { Name = "Kayak", Price = 275M}, new Product() { Name = "Lifejacket", Price = 48.95M}, new Product() { Name = "Soccer ball", Price = 19.50M}, new Product() { Name = "Stadium", Price = 79500M} }; } public virtual decimal CalculateStockValue() { // calculate the total value of the products decimal totalValue = calculator.ValueProducts(products); // return the result return totalValue; } } class Program { static void Main(string[] args) { IKernel ninjectKernel = new StandardKernel(); // define the bindings ninjectKernel.Bind<IValueCalculator>().To<IterativeValueCalculator> ().WhenInjectedInto<ShoppingCartTwo>(); ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>(); // create the carts and inject the dependency ShoppingCart cart = new ShoppingCart(ninjectKernel.Get<IValueCalculator>()); ShoppingCartTwo cartTwo = new ShoppingCartTwo(ninjectKernel.Get<IValueCalculator>()); // perform the calculation and write out the result Console.WriteLine("Total: {0:c}", cart.CalculateStockValue()); Console.WriteLine("Total: {0:c}", cartTwo.CalculateStockValue()); Console.Read(); } } } 
+4
source share
1 answer

I think your problem is that: -

 ninjectKernel.Get<IValueCalculator>() 

evaluates before it is passed to your constructor.

i.e. it is called out of context of the binding.

Instead of updating the object yourself, use your kernel to get an instance of the object.

 var shopCartTwo = ninjectKernel.Get<ShoppingCartTwo>(); 

Note that you are not passing a parameter at all. Ninject will look at the signature of the constructor, work that there is an unresolved dependency, and use the appropriate contextual binding.

+5
source

Source: https://habr.com/ru/post/1390227/


All Articles