我正在尝试使用一个IoC框架,我选择了使用Unity.com。我仍然不完全理解的一件事是如何在应用程序中更深入地解析对象。我想我只是还没把电灯泡弄清楚。
因此,我试图在psuedo‘’ish代码中执行如下操作
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);
}
}我可以看到三个选择:
编辑我不清楚的一件事是,我想为foreach语句的每一次迭代创建一个新的测试用例实例。上面的示例需要解析测试套件配置并填充测试用例对象的集合。
发布于 2010-03-05 12:27:55
正确的DI方法是使用构造器注入或其他DI模式(但最常见的是构造器注入)将依赖项注入到消费者,而不管DI容器如何。
在您的示例中,您似乎需要依赖项TestSuite和TestCase,因此您的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,在这种情况下,您可能希望使用注入抽象工厂而不是单个TestCase。)
在您的成分根中,您可以配置统一(或任何其他容器):
container.RegisterType<TestSuite, ConcreteTestSuite>();
container.RegisterType<TestCase, ConcreteTestCase>();
container.RegisterType<TestSuiteParser>();
var parser = container.Resolve<TestSuiteParser>();当容器解析TestSuiteParser时,它理解构造器注入模式,因此自动连接实例和它所需的所有依赖项。
创建单个容器或传递容器只是服务定位器反模式的两个变体,所以我不建议这样做。
发布于 2012-12-17 23:31:37
我是Dependency Injection的新手,我也有过这个问题。我很难把注意力放在DI上,主要是因为我专注于将DI应用于我正在处理的一个类,一旦我将依赖项添加到构造函数中,我立即试图找到某种方法将统一容器带到需要实例化该类的位置,以便能够在类上调用Resolve方法。因此,我一直在考虑将统一容器作为静态容器全局可用,或者将其封装在单个类中。
我读了这里的答案,并不真正理解所解释的是什么。最后帮助我“得到它”的是这篇文章:
http://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container
这一段特别是“灯泡”时刻:
"99%的代码库应该不了解您的IoC容器。只有根类或引导程序才使用该容器,即使这样,构建依赖关系图并启动应用程序或请求所需的通常是一个解析调用。“
本文帮助我理解,实际上我不能访问整个应用程序的统一容器,而只能访问应用程序的根。因此,我必须将DI原则反复应用到应用程序的根类。
希望这能帮助那些和我一样困惑的人!:)
发布于 2010-03-05 12:22:46
您不应该真的需要在应用程序的很多地方直接使用容器。您应该在构造函数中获取所有的依赖项,而不是从您的方法中找到它们。你的例子可以是这样的:
public class TestSuiteParser : ITestSuiteParser {
private TestSuite testSuite;
public TestSuitParser(TestSuit testSuite) {
this.testSuite = testSuite;
}
TestSuite Parse(XPathNavigator someXml)
{
List<XPathNavigator> aListOfNodes = DoSomeThingToGetNodes(someXml)
foreach (XPathNavigator blah in aListOfNodes)
{
//I don't understand what you are trying to do here?
TestCase testCase = ??? // I want to get this from my Unity Container
testSuite.TestCase.Add(testCase);
}
}
}然后在整个应用程序中都采用同样的方式。当然,在某一时刻,你必须解决一些问题。例如,在asp.net mvc中,这个位置位于控制器工厂。这就是创建控制器的工厂。在这个工厂中,您将使用容器来解析控制器的参数。但是这只是整个应用程序中的一个地方(当您做更高级的东西时,可能会有更多的地方)。
还有一个很好的项目叫做CommonServiceLocator。这是一个项目,它为所有流行的ioc容器提供了一个共享接口,这样您就不会依赖于特定的容器。
https://stackoverflow.com/questions/2386487
复制相似问题