2016-09-21 10 views
0

В следующих тестах единицы, TestDirectRetrieval_WithNoImplementations и TestInjection_WithNoImplementations неудачуКак поддерживать динамическую multiinjection с Ninject, где может быть никакие пункты не связаны

[TestFixture] 
public class KernelTests 
{ 
    [Test] //Passes 
    public void TestDirectRetrieval_WithMultipleImplementations() 
    { 
     //Arrange 
     var kernel = new StandardKernel(); 
     kernel.Bind<Foo>().ToConstant(new Foo("a")); 
     kernel.Bind<Foo>().ToConstant(new Foo("b")); 
     //Act + Assert 
     Assert.DoesNotThrow(() => kernel.GetAll<Foo>().ToList()); 
    } 

    [Test] //Passes 
    public void TestInjection_WithMultipleImplementations() 
    { 
     //Arrange 
     var kernel = new StandardKernel(); 
     kernel.Bind<Foo>().ToConstant(new Foo("a")); 
     kernel.Bind<Foo>().ToConstant(new Foo("b")); 
     //Act + Assert 
     Assert.DoesNotThrow(() => kernel.Get<Bar>()); 
    } 

    [Test] //Fails 
    public void TestDirectRetrieval_WithNoImplementations() 
    { 
     //Arrange 
     var kernel = new StandardKernel(); 
     //Act + Assert 
     Assert.DoesNotThrow(() => kernel.GetAll<Foo>().ToList()); 
    } 

    [Test] //Fails 
    public void TestInjection_WithNoImplementations() 
    { 
     //Arrange 
     var kernel = new StandardKernel(); 
     //Act + Assert 
     Assert.DoesNotThrow(() => kernel.Get<Bar>()); 
    } 

    #region Test helper classes 

    class Foo 
    { 
     public Foo(string someArgThatCantBeAutomaticallyResolvedByNinject){} 
    } 

    class Bar 
    { 
     private List<Foo> myFoos; 

     public Bar(IEnumerable<Foo> foos) 
     { 
      myFoos = foos.ToList(); 
     } 
    } 
    #endregion 
} 

В сценарии были кто-то является обязательным вещи для констант/реализаций на основе некоторых динамическая ситуация, как они могут поддержать дело, ничто не связано вообще?

ответ

1

GetAll не используется ninject для инъекций, но, как вы выяснили, он обеспечивает желаемое поведение. Чтобы включить инъекцию 0-п семантикой я обычно ролл свою собственную «коллекцию», код версия неполных/псевдо выглядит следующим образом:

class OptionalItems<T> : IEnumerable<T> 
{ 
    private readonly T[] items; 

    public OptionalItems(IResolutionRoot resolutionRoot) 
    { 
     this.items = resolutionRoot.TryGetAll(T).ToArray(); 
    } 

    public IEnumerator<T> GetEnumerator() { 
     return this.items.GetEnumerator(); 
    } 
} 

Теперь впрыснуть OptionalItems вместо IEnumerable<T> или IList<T>. Для целей тестирования может иметь смысл создать интерфейс для OptionalItems: public interface IOperationalItems<T> : IEnumerable<T> и связать это.

+0

Как правило, вы просто связываете один элемент «IOptionalItems' /' OptionalItems »с открытым общим параметром или по одному для каждого необязательного типа? – Landerah

+0

И я замечаю, что это влияет на разрешение IEnumerable во время разрешения. Разве это отличается от поведения при введении IEnumerable? Я нашел [это] (https://github.com/ninject/ninject/issues/128) (может быть, ваш запрос?), Но, похоже, он не был реализован. (Очевидно, что Lazy не совсем то же самое из-за того, что это разрешение только один раз) – Landerah

+0

Обычно я связываю его с открытым общим. В случае, если вам нужны конкретные области ('InSingletonScope()', 'InRequestScope()') для определенных типов, вам также придется создавать определенные привязки. Да, вопрос № 128 был создан мной. Мы обсудили с Ремо-Глором, который долгое время поддерживал и двигал силу для Ninject, и он сам сказал, что опасно * не * материализовать 'IEnumerable' в ctor. Таким образом, я сделал это безопасный и рекомендуемый способ. – BatteryBackupUnit