我想将我注入的对象聚合到一个Data对象中,这样我就不必拥有大的构造函数列表。但是我仍然希望使用WhenInjectedInto来提供上下文绑定。
例如,下面的规范测试了一个我认为有帮助的场景
WhenInjectedIntoRequestChain
表示只应在源位置使用绑定 注入已被注入parent0,其本身已被注入parent1,依此类推
该方法应具有签名
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 :(得分: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;
}
}
}