与IList的Ninject层叠式Inection

时间:2011-01-03 21:57:30

标签: ninject

我正在尝试使用Ninject将嵌入式注入实现到包含IList字段的类中。看来,除非我专门指定要在kernel.Get方法中使用的每个绑定,否则IList属性总是注入一个默认对象的列表。

以下VSTest代码说明了该问题。第一个测试失败,因为IList字段包含一个Name = null的MyType对象。第二个测试通过,但我必须专门告诉Ninject使用什么构造函数参数。我正在使用MVC 3的ninject.web.mvc项目的最新版本。

Ninject是否特别对待IList不同,还是有更好的方法来解决这个问题?请注意,这在使用IList时似乎只是一个问题。创建包装IList的自定义集合对象在第一个测试中按预期工作。

[TestClass()]
public class NinjectTest
{
    [TestMethod()]
    public void ListTest_Fails_NameNullAndCountIncorrect()
    {
        var kernel = new Ninject.StandardKernel(new MyNinjectModule());
        var target = kernel.Get<MyModel>();
        var actual = target.GetList();

        // Fails. Returned value is set to a list of a single object equal to default(MyType) 
        Assert.AreEqual(2, actual.Count());  

        // Fails because MyType object is initialized with a null "Name" property
        Assert.AreEqual("Fred", actual.First().Name); 
    }

    [TestMethod()]
    public void ListTest_Passes_SeemsLikeUnnecessaryConfiguration()
    {
        var kernel = new Ninject.StandardKernel(new MyNinjectModule());

        var target = kernel.Get<MyModel>(new ConstructorArgument("myGenericObject", kernel.Get<IGenericObject<MyType>>(new ConstructorArgument("myList", kernel.Get<IList<MyType>>()))));

        var actual = target.GetList();
        Assert.AreEqual(2, actual.Count());  
        Assert.AreEqual("Fred", actual.First().Name); 
    }
}

public class MyNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<IList<MyType>>().ToConstant(new List<MyType> { new MyType { Name = "Fred" }, new MyType { Name = "Bob" } });
        Bind<IGenericObject<MyType>>().To<StubObject<MyType>>();
    }
}

public class MyModel
{
    private IGenericObject<MyType> myGenericObject;

    public MyModel(IGenericObject<MyType> myGenericObject)
    {
        this.myGenericObject = myGenericObject;
    }

    public IEnumerable<MyType> GetList()
    {
        return myGenericObject.GetList();
    }
}

public interface IGenericObject<T>
{
    IList<T> GetList();
}

public class StubObject<T> : IGenericObject<T>
{
    private IList<T> _myList;

    public StubObject(IList<T> myList)
    {
        _myList = myList;
    }

    public IList<T> GetList()
    {
        return _myList;
    }
}

public class MyType
{
    public String Name { get; set; }
}

1 个答案:

答案 0 :(得分:4)

列表,集合和数组的处理略有不同。对于这些类型,ninject将注入包含泛型类型的所有绑定实例的列表或数组。在您的情况下,实现类型是一个默认情况下为aoutobound的类。所以列表将包含该类的一个实例。如果您向该类添加一个接口并使用该接口,则该列表将为空。