2016-12-15 5 views
0

Я хотел бы объединить мои введенные объекты в объект Data, чтобы у меня не было больших списков конструкторов. Однако я все же хочу использовать InInjectedInto для предоставления контекстной привязки.Как перенастроить ninject over-injection в более сухую форму

Например, ниже спецификации тестирует сценарий, который я считаю, поможет

WhenInjectedIntoRequestChain

Указывает, что связывание следует использовать только там, где источник был введен был введен в parent0, который сам по себе имеет был введен в Parent1 и так далее

метод должен иметь signiture

public static IBindingInNamedWithOrOnSyntax<T> 
     WhenInjectedIntoRequestChain<T> 
      (this IBindingWhenInNamedWithOrOnSyntax<T> @this 
      , params Type[] parentChain 
      ) 

В спецификации используется для тестирования, это должно быть

using System.Collections.Generic; 
using System.Linq; 
using FluentAssertions; 
using Ninject; 
using Weingartner.Controls.PluginFramework; 
using Xunit; 

namespace Weingartner.Controls.Spec.PluginFramework 
{ 
    public class NinjectExtensionsSpec 
    { 
     public interface IData { } 

     public class Data0 : IData {} 
     public class Data1 : IData {} 
     public class Data2 : IData {} 

     public class Params 
     { 
      public IList<IData> Data { get; set; } 

      public Params(IEnumerable<IData> data) 
      { 
       Data = data.ToList(); 
      } 

     } 

     public class Target0 
     { 
      public Params P { get; set; } 
      public Target0(Params p) {P = p;} 
     } 

     public class Target1 
     { 
      public Params P { get; set; } 
      public Target1(Params p){P = p;} 
     } 

     [Fact] 
     public void WhenInjectedIntoHeirarchyShouldWork() 
     { 
      var k = new StandardKernel(); 

      k.Bind<IData>().To<Data0>() 
      .WhenInjectedIntoRequestChain(typeof(Params),typeof(Target0)); 
      k.Bind<IData>().To<Data1>() 
      .WhenInjectedIntoRequestChain(typeof(Params),typeof(Target1)); 
      k.Bind<IData>().To<Data2>() 
      .WhenInjectedIntoRequestChain(typeof(Params),typeof(Target1)); 


      var target0 = k.Get<Target0>(); 
      var target1 = k.Get<Target1>(); 

      target0.P.Data.Count.Should().Be(1); 
      target1.P.Data.Count.Should().Be(2); 


     } 

    } 
} 

ответ

0

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

using System; 
using System.Linq; 
using Ninject.Activation; 
using Ninject.Infrastructure.Language; 
using Ninject.Syntax; 

namespace Weingartner.Controls.PluginFramework 
{ 
    public static class NinjectExtensions 
    { 

     /// <summary> 
     /// Indicates that the binding should only be used where the source 
     /// has been injected into parentChain[0] which in turn has been injected 
     /// into parentChain[1] and son on 
     /// </summary> 
     /// <param name="parentChain">This list of parents in order</param> 
     /// <returns>The fluent syntax.</returns> 
     public static IBindingInNamedWithOrOnSyntax<T> 
      WhenInjectedIntoRequestChain<T> 
       (this IBindingWhenInNamedWithOrOnSyntax<T> @this 
       , params Type[] parentChain 
       ) 
     { 

      @this.BindingConfiguration.Condition = 
       request => 
       { 
        var result = true; 
        foreach (var parent in parentChain) 
        { 
         result = result && WhenInjectedInto(request, parent); 
         request = request?.ParentRequest; 
        } 
        return result; 
       }; 

      return (IBindingInNamedWithOrOnSyntax<T>)@this; 
     } 

     private static bool WhenInjectedInto(IRequest request, Type parent) 
     { 
      if (!parent.IsGenericTypeDefinition) 
       return request?.Target != null 
        && parent.IsAssignableFrom(request.Target.Member.ReflectedType); 

      if (!parent.IsInterface) 
       return request 
        ?.Target?.Member.ReflectedType 
        .GetAllBaseTypes() 
        .Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == parent) 
        ?? false; 

      return request 
       ?.Target?.Member.ReflectedType? 
       .GetInterfaces() 
       .Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == parent) 
       ?? false; 
     } 
    } 
}