Реализация внедрения условной зависимости с помощью ninject и c # .net - PullRequest
4 голосов
/ 10 января 2012

Я пытаюсь изучить основы внедрения зависимостей (DI). С этой целью я предпринял учебник, который демонстрирует использование Ninject для DI через создание консольного приложения C #.

Приложение, по сути, нацелено на то, чтобы иметь возможность рассчитывать стоимость товаров в корзине, используя различные методы расчета.

Классы в приложении:

  • Простая модель товара
  • два класса корзины покупок, которые действуют как простые обертки вокруг коллекции Товаров
  • Интерфейс ValueCalculator, который требует метод ValueProducts, который возвращает некоторое количество товаров в корзинах
  • Две отдельные реализации интерфейса ValueCalculator (итеративный подход и подход LINQ)

Я попытался использовать условное внедрение с помощью метода расширения .WhenInjectedTo, чтобы объект ShoppingCart получал инъекцию LinqValueCalculator, а объект ShoppingCartTwo - инъекцию IterativeValueCalulator. Однако в обоих случаях вводится LinqValueCalculator.

См. Код ниже

 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();
    }
}
}

1 Ответ

5 голосов
/ 10 января 2012

Я думаю, что ваша проблема в том, что: -

ninjectKernel.Get<IValueCalculator>()

оценивает перед тем, как передается в ваш конструктор.

т.е. он вызывается вне контекста связывания.

Вместо того, чтобы самостоятельно создавать новый объект, используйте ядро ​​для получения экземпляра объекта.

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

Обратите внимание, что вы вообще не передаете параметр. Ninject изучит сигнатуру конструктора, определит наличие неразрешенной зависимости и использует соответствующую контекстную привязку.

...