1

我正在使用 StructureMap 2.6.4.0。我使用它的主要目标是简化我的测试。根据 StructureMap 文档(此处),它有一个很棒的临时模拟注入功能(ObjectFactory.Inject<>())。

如果我错了,请纠正我,但这是我对该功能的理解:

  1. 您将容器配置代码放在一个地方,所有“真实”实现都映射到它们的接口。
  2. 在每次测试运行之前,您都根据与您的应用程序相同的代码来初始化您的 ObjectFactory。
  3. 如果任何测试需要用“测试”替换一些“真实”实现,它会使用 ObjectFactory 上的 Inject 方法注入“测试”实现。
  4. 要恢复原始映射并删除注入的模拟,您需要调用 ResetDefaults()。

我的问题在第四步。

这是一个代码示例,它说明了我的问题:

public interface IValueProvider
{
    string GetValue();
}

public class ValueProvider : IValueProvider
{
    public string GetValue()
    {
        return "Value provider";
    }
}

public class TestValueProvider : IValueProvider
{
    public string GetValue()
    {
        return "Test value provider";
    }
}

class Program
{
    static void Main(string[] args)
    {
        ObjectFactory.Initialize(x => x.For<IValueProvider>().Use<ValueProvider>());

        var valueProvider = ObjectFactory.GetInstance<IValueProvider>();
        Console.WriteLine(valueProvider.GetValue());
        // I will see expected "Value provider"


        ObjectFactory.Inject<IValueProvider>(new TestValueProvider());
        valueProvider = ObjectFactory.GetInstance<IValueProvider>();
        Console.WriteLine(valueProvider.GetValue());
        // I will see expected "Test value provider"


        ObjectFactory.ResetDefaults();
        valueProvider = ObjectFactory.GetInstance<IValueProvider>();
        Console.WriteLine(valueProvider.GetValue());
        // I will see NOT expected "Test value provider".
        // Doesn't ResetDefaults() have to restore a ValueProvider implementation?
    }
}

那么,谁能告诉我我错在哪里?或者它可能是 StructureMap 中的错误?

4

1 回答 1

1

ResetDefaults()方法将配置文件切换到String.Empty。在你的情况下它已经是。这不会删除通过Inject<T>(T object).

Inject<T>(T object)方法将对象注册为 PluginType "T" 的默认值。换句话说,它会覆盖您当前的默认值,即具体类型ValueProvider

StructureMap 的文档已经过时了,所以我的猜测是,在早期版本中,它的工作方式与文档中描述的方式相同,但情况已不再如此。

因此,Inject<T>(T object)仅当您想在运行时覆盖已配置插件类型的默认值或使用 StructureMap 配置文件时才使用该方法。

StructureMap 确实提供了一些从容器中删除“弹出”类型的方法。其中之一是:

ObjectFactory.Model.EjectAndRemoveTypes(match =>            
            match != null &&
                   match == typeof (TestValueProvider)
);

此代码确实删除了该Inject<T>(T object)方法所做的注册,但不会恢复 type 的默认实例IValueProvider。这意味着不再有IValueProvider.

因此ObjectFactory.GetInstance<IValueProvider>()会抛出StructureMap Exception Code: 202 No Default Instance defined for PluginFamily ...异常。

ObjectFactory.GetAllInstances<IValueProvider>().First()会给你返回的实例ValueProvider。你期望的那个。

我不确定您要在这里测试什么,但如果它们是单元测试,您应该尽量避免需要 IoC 容器(这也意味着依赖于ObjectFactory)。如果您确实需要一个容器,请使用IContainer您可以自己管理和创建的抽象。支持这一点的其他 SO 问题的一些链接是:

于 2013-11-03T18:53:06.263 回答