一尘不染

创建单例访问统一容器或将其传递给应用程序更好吗?[关闭]

c#

我专心使用IoC框架,并且选择使用Unity。我仍然不完全了解的一件事是如何在应用程序的更深处解析对象。我怀疑我只是没有把灯泡弄清楚。

所以我正在尝试在伪代码中执行以下操作

void Workflow(IUnityContatiner contatiner, XPathNavigator someXml)
{
   testSuiteParser = container.Resolve<ITestSuiteParser>
   TestSuite testSuite = testSuiteParser.Parse(SomeXml) 
   // Do some mind blowing stuff here
}

因此,testSuiteParser.Parse执行以下操作

TestSuite Parse(XPathNavigator someXml)
{
    TestStuite testSuite = ??? // I want to get this from my Unity Container
    List<XPathNavigator> aListOfNodes = DoSomeThingToGetNodes(someXml)

    foreach (XPathNavigator blah in aListOfNodes)
    {
        //EDIT I want to get this from my Unity Container
        TestCase testCase = new TestCase() 
        testSuite.TestCase.Add(testCase);
    } 
}

我可以看到三个选项:

  1. 创建一个Singleton存储我可以在任何地方访问的unity容器。我真的不喜欢这种方法。像这样添加一个依赖项以使用依赖项注入框架似乎有些奇怪。
  2. 将IUnityContainer传递给我的TestSuiteParser类及其每个子类(假定它的深度为n个级别,或者实际上为3个级别)。到处传递IUnityContainer看起来很奇怪。我可能只需要克服这一点。
  3. 使灯泡时刻正确地使用Unity。希望有人可以帮助您完成切换。

[编辑]我不清楚的一件事是,我想为foreach语句的每次迭代创建一个新的测试用例实例。上面的示例需要解析测试套件配置并填充测试用例对象的集合


阅读 214

收藏
2020-05-19

共1个答案

一尘不染

DI的正确方法是使用 构造函数注入 或其他DI模式(但最常见的是Constructor Injection)将依赖项注入到使用者中, 而与DI
Container无关

在您的示例中,看起来您需要依赖项TestSuiteTestCase,因此您的TestSuiteParser类应通过(仅)构造函数要求它们来
静态声明 它需要这些依赖项:

public class TestSuiteParser
{
    private readonly TestSuite testSuite;
    private readonly TestCase testCase;

    public TestSuiteParser(TestSuite testSuite, TestCase testCase)
    {
        if(testSuite == null)
        {
            throw new ArgumentNullException(testSuite);
        }
        if(testCase == null)
        {
            throw new ArgumentNullException(testCase);
        }

        this.testSuite = testSuite;
        this.testCase = testCase;
    }

    // ...
}

通知如何组合readonly关键字和保护条款保护类的不变量,确保依赖 提供给TestSuiteParser的任何成功创建实例。

您现在可以像这样实现Parse方法:

public TestSuite Parse(XPathNavigator someXml) 
{ 
    List<XPathNavigator> aListOfNodes = DoSomeThingToGetNodes(someXml)

    foreach (XPathNavigator blah in aListOfNodes) 
    { 
        this.testSuite.TestCase.Add(this.testCase); 
    }  
}

(但是,我怀疑可能涉及多个TestCase,在这种情况下,您可能想注入一个Abstract
Factory
而不是一个TestCase。)

在您的Composition Root中,您可以配置Unity(或任何其他容器):

container.RegisterType<TestSuite, ConcreteTestSuite>();
container.RegisterType<TestCase, ConcreteTestCase>();
container.RegisterType<TestSuiteParser>();

var parser = container.Resolve<TestSuiteParser>();

当容器解析TestSuiteParser时,它将理解构造函数注入模式,因此它将 自动 连接实例及其所有必需的依赖项。

创建Singleton容器或将容器四处传递只是Service
Locator反模式的
两个变体,所以我不建议这样做。

2020-05-19