0

免责声明:我对 Ninject 和 DI 很陌生。另外,我没有和Ninject结婚。如果有人想解释这将如何在 Windsor、Unity、SourceMap 或其他东西中工作,我会全力以赴。

我有以下处理存储类型对象的类TArchived

public class Archiver<TArchived> where TArchived : class
{
    public Archiver(Func<string> getName, IStore<TArchived> storage, Func<TArchived> getInitialState);
}

创建的实例时,它会尝试在具有从 返回的名称的实例Archiver中查找。如果没有实例,它会创建一个具有从 . 返回的默认值的实例。storagegetName()getInitialState()

下一个类用于Archiver存储项目列表。但是,虽然该项目列表的大小永远不会改变,但该列表在编译时是未知的

public class MyClass
{
    public class Item
    {
        public string Value { get; set; }
    }

    public MyClass(Archiver<Item[]> archiver)
    {
        Archiver = archiver;
    }

    public static Item[] GetInitialState(IEnumerable<string> values)
    {
        return values.Select(value => new Item { Value = value }).ToArray();
    }

    public Archiver<Item[]> Archiver { get; private set; }
}

我已经像这样设置了 Ninject:

public class Tests
{
    private IKernel Ninject { get; set; }

    public Tests()
    {
        Ninject = new StandardKernel();
        Ninject.Bind<IStore<MyClass.Item[]>>().To<MemoryStore<MyClass.Item[]>>();

        Ninject.Bind<Archiver<MyClass.Item[]>>().To<Archiver<MyClass.Item[]>>()
            .WithConstructorArgument("getName", new Func<string>(() => "TEST"))
            .WithConstructorArgument("getInitialState", new Func<MyClass.Item[]>(MyClass.GetInitialState(/* what here? */)));
    }

    [Fact]
    public void Test()
    {
        // testing options
        var tests = new[] { "A", "B" };

        var myClass = Ninject.Get<MyClass>();
    }

    [Fact]
    public void Test_2()
    {
        // different testing options
        var tests = new[] { "A", "B", "C" };

        var myClass = Ninject.Get<MyClass>();
    }
}

但我很困惑为getInitialState参数添加什么。如果我想要不同的项目存储列表MyClass,我需要将不同的项目传递给GetInitialState函数。

4

3 回答 3

1

经过更多的实验,这些是我想出的最佳解决方案。我很想看到更好的方法。

[Fact]
public void Test()
{
    Ninject.Bind<Func<MyClass.Item[]>>().ToProvider<Func<MyClass.Item[]>>(new CallbackProvider<Func<MyClass.Item[]>>((ctx) => () => MyClass.GetInitialState(new[] { "A", "B" })));
    var myClass = Ninject.Get<MyClass>();
}

[Fact]
public void Test2()
{
    Ninject.Bind<Func<MyClass.Item[]>>().ToConstant<Func<MyClass.Item[]>>(() => MyClass.GetInitialState(new[] { "A", "B", "C" }));
    var myClass = Ninject.Get<MyClass>();
}
于 2012-08-21T18:56:57.733 回答
0

您可以从绑定中拉出构造函数参数,并将其添加到解析点。所以使用这个绑定:

Ninject.Bind<Archiver<MyClass.Item[]>>().To<Archiver<MyClass.Item[]>>()
    .WithConstructorArgument("getName", new Func<string>(() => "TEST"));

然后在每个单元测试中使用它,根据需要更改getInitialState的值:

var myClass = Ninject.Get<MyClass>()
    .WithConstructorArgument("getInitialState", 
        new Func<MyClass.Item[]>(MyClass.GetInitialState(new string[] { "1", "2", "3" }))
    );
于 2012-08-21T17:35:44.247 回答
0

我没有深入研究您的问题,但在我看来,您正在寻找命名范围或非常接近的东西,作为在更高级别管理此类事情的一种方式。我建议从那里链接到@Remo Gloor 关于这些主题的博客文章(并将任何缺失的文章添加到NamedScope 扩展 wiki 中:D)。

于 2012-08-22T21:57:35.017 回答