C# IoC 容器示例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/770039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 00:28:17  来源:igfitidea点击:

Examples of IoC Containers

c#inversion-of-control

提问by Morph

Does anyone have good examples of IoC containers (preferably in c#) and how and why to use them ? I have checked out the wiki pageand Ayende'sexample, but I don't quite get the concept yet.

有没有人有 IoC 容器的好例子(最好在 c# 中)以及如何以及为什么使用它们?我已经查看了wiki 页面Ayende 的示例,但我还不太明白这个概念。

And when and where should I use an IoC container ?

我应该何时何地使用 IoC 容器?

采纳答案by Jab

I've used StructureMapquite a bit. The rest of your question is pretty loaded. I'll try to explain the concept in an example.

我已经使用了很多StructureMap。你的问题的其余部分非常重要。我将尝试在一个例子中解释这个概念。

Suppose you created a website that will accept payments through PayPal. PayPal is now a dependency. But you don't want to code against a specific PayPal provider.

假设您创建了一个接受 PayPal 付款的网站。PayPal 现在是一个依赖项。但是您不想针对特定的 PayPal 提供商进行编码。

Instead, you would create and code against an interface like this:

相反,您将针对这样的接口创建和编码:

interface IPaymentProcessor
{
    bool ProcessPayment(amount, ....);
}

All your PayPal code would reside in a class that implements the methods of your interface - PayPalPaymentProcessor, for example.

例如,您的所有 PayPal 代码都将驻留在实现接口方法的类中PayPalPaymentProcessor

Now you have an object that you will actually use to process the payments. This could be a Controller (ASP.NET-MVC, ViewModel-WPF) or just a class as shown here:

现在您有了一个实际用于处理付款的对象。这可能是一个控制器(ASP.NET-MVC、ViewModel-WPF)或只是一个类,如下所示:

class PaymentProcessor
{
    private IPaymentProcessor _processor = null;
    public PaymentProcessor(IPaymentProcessor processor)
    {
        _processor = processor;
    }

    public bool ProcessTransaction(Transaction trans)
    {
       _processor.ProcessPayment(trans.amount, ...);
    }
}

This is where an IoC container comes in. Instead of you calling the constructor manually, you would let an IoC container injectthe dependency:

这就是 IoC 容器的用武之地。 您可以让 IoC 容器注入依赖项,而不是手动调用构造函数:

PaymentProcessor processor = ObjectFactory.GetInstance<PaymentProcessor>();

This piece of code tells StructureMap "Anytime you see a constructor that needs an IPaymentProcessor, return a new PayPalPaymentProcessor".

这段代码告诉 StructureMap“任何时候你看到一个需要 的构造函数IPaymentProcessor,返回一个新的PayPalPaymentProcessor”。

ObjectFactory.Initialize(x =>
{ 
    x.ForRequestedType<IPaymentProcessor>().TheDefaultIsConcreteType<PayPalPaymentProcessor>();
});

All this mapping is separate from your implementation code and you could swap out these at a later point with little refactoring needed. There is a lot more to IoC containers, but that the basic concept. You can automate the injection of constructors to avoid the calls directly to ObjectFactoryas well.

所有这些映射都与您的实现代码分开,您可以在稍后更换它们,几乎不需要重构。IoC 容器还有很多,但这是基本概念。您也可以自动注入构造函数以避免直接调用ObjectFactory

Hope this helps!

希望这可以帮助!

回答by Piotr Czapla

Check out Spring IoC (.net)a java/.net container. The documentation is quite good introduction.

查看Spring IoC (.net)一个 java/.net 容器。该文档是相当不错的介绍。

In a brief: You can think about IoC as an architecture that encourage: objects compositionand programming to an interface.

简而言之:您可以将 IoC 视为一种鼓励:对象组合编程到接口的架构 。

This gives you the following:

这为您提供以下内容:

  • the ability to unit test your code easily (you can easily test your objects in isolation by mocking up all its dependencies).

  • An extremely advance configuration (because your program with IoC is just bunch of objects and an configuration that glues the objects together).

  • The ability to extend or modify byte compiled application (this is true for Java I'm not sure if it is true for .net).

  • 能够轻松地对您的代码进行单元测试(您可以通过模拟其所有依赖项来轻松地单独测试您的对象)。

  • 一个非常高级的配置(因为你的 IoC 程序只是一堆对象和一个将对象粘合在一起的配置)。

  • 扩展或修改字节编译应用程序的能力(对于 Java 来说是这样,我不确定 .net 是否如此)。

回答by Satish

Are you trying to build a IoC container why not use one of the available ones like Spring.NET, StructureMap or Unity Application Block? Hereis a list of open-source IoC projects

您是否正在尝试构建 IoC 容器,为什么不使用可用的容器之一,例如 Spring.NET、StructureMap 或 Unity Application Block?是开源 IoC 项目的列表

回答by Steve Willcock

I normally use StructureMap- mostly because I'm familiar with the syntax. I've also heard good things about autofacand I'm looking forward to trying out Ninjectwhen it hits v2.

我通常使用StructureMap- 主要是因为我熟悉语法。我也听说过有关autofac 的消息,我期待着在Ninject达到 v2 时试用它。

You might want to take a look at this answerwhere I talk about a basic usage of an IoC container (I always think things are easier to understand with a simple example) - that might help you to understand things a little more. Basically, the IoC container helps you to build objects with all the dependencies satisfied, and allows you to change your dependencies with minimal configuration code.

您可能想看看这个答案,其中我谈到了 IoC 容器的基本用法(我总是认为通过一个简单的示例更容易理解)-这可能会帮助您更多地理解事物。基本上,IoC 容器可帮助您构建满足所有依赖项的对象,并允许您以最少的配置代码更改依赖项。

回答by Jeffrey Cameron

We use Ninject because of its simple API and fast resolution of objects. It's very well documented and leverages C# 3.0 features like lambda expressions to make specification easier.

我们使用 Ninject 是因为它简单的 API 和快速的对象解析。它有很好的文档记录,并利用 C# 3.0 特性(如 lambda 表达式)来简化规范。

You can find several screencasts on Ninject here

您可以在此处找到有关 Ninject 的几个截屏视频

回答by Jozef Izso

Try reading Introduction to Unity Application Blockand in ASP.NET StoreFront: Dependency Injectionscreencast you can see more about Dependency Injection concepts.

尝试阅读Unity 应用程序块简介,在ASP.NET StoreFront:依赖注入截屏视频中,您可以看到有关依赖注入概念的更多信息。

回答by James Black

I am using Unity for my IoC container, but the difference between the containers resides in more than what you can do with DI.

我将 Unity 用于我的 IoC 容器,但容器之间的区别不仅仅在于您可以使用 DI 做什么。

DI (Dependency Injection) is mainly a way to get more loose coupling between disparate parts of your program. So, if you wrote a game that you like how it works, by using DI you can change the characters or physics engine in the game without changing other parts of the game, so, if someone pays more money they get the more realistic engine, or the better characters, but since nothing else is changing, the testing is simpler.

DI(依赖注入)主要是一种在程序的不同部分之间获得更多松散耦合的方法。所以,如果你写了一个你喜欢它的工作方式的游戏,通过使用 DI,你可以改变游戏中的角色或物理引擎,而无需改变游戏的其他部分,所以,如果有人支付更多的钱,他们就会得到更逼真的引擎,或者更好的字符,但由于没有其他变化,测试更简单。

Unit testing is also easier with DI as you can mock out the database, for example, by just changing the implementation that will be used by the application, without affecting anything else.

使用 DI 进行单元测试也更容易,因为您可以模拟数据库,例如,只需更改应用程序将使用的实现,而不会影响其他任何内容。

If you use Spring.NET for example, you will get access to a very powerful framework, but it may do a great deal that you won't use, so look for something smaller. I think the best rule is to find the smallest, simplest implementation that meets your needs, and use that.

例如,如果您使用 Spring.NET,您将可以访问一个非常强大的框架,但它可能会做很多您不会使用的事情,因此请寻找更小的东西。我认为最好的规则是找到满足您需求的最小、最简单的实现,并使用它。

回答by Joseph

If you want to see an IoC container under the hood, and also the point (Dependency Injection), there's a great podcast on DNR TV (Episode 126) that really goes into detail about how to create them, why you'd need them. It's a really wonderful podcast. Once you've watched this video, you'll then be able to look at Unity,Ninject, StructureMap, etc and be able to understand what they're doing

如果您想在引擎盖下看到 IoC 容器,以及重点(依赖注入),DNR TV(第 126 集)上有一个很棒的播客,其中详细介绍了如何创建它们,为什么需要它们。这是一个非常棒的播客。观看此视频后,您将能够查看UnityNinjectStructureMap等,并能够理解它们在做什么

回答by Joseph

Be aware of the following limitations of the IOC container. I have to warn people, because I am living with the hell of having to support a system using it:

请注意 IOC 容器的以下限制。我必须警告人们,因为我不得不支持使用它的系统:

  • Exceptions thrown by constructors get swallowed. You only get the “couldn't create dependency” exception. That means you can't catch expected exceptions if it's throw in a constructor.
  • Can't step through constructors.
  • Forgetting to register an interface breaks at runtime instead of compile time.
  • All your classes can only have one constructor and they all have to accept interfaces as parameters.
  • All dependencies are instantiated so you can't share instances, which means your memory usage can get large quickly.
  • It promotes a lot of interdepencies which can hide the fact that you code has turned into spaghetti. Making it easier to instatiate all of these interdepencies just masks that there is a potential underlying problem.
  • You can't manage your own "Unit of Work" very easily because you can't manage a transaction across multiple dependencies since you didn't have control of instantiating them and passing in the context of that transaction.
  • 构造函数抛出的异常被吞噬。您只会收到“无法创建依赖项”异常。这意味着如果在构造函数中抛出异常,您将无法捕获预期的异常。
  • 无法通过构造函数。
  • 忘记注册接口会在运行时而不是编译时中断。
  • 你所有的类只能有一个构造函数,而且它们都必须接受接口作为参数。
  • 所有依赖项都已实例化,因此您无法共享实例,这意味着您的内存使用量会很快变大。
  • 它促进了许多相互依赖,这可以隐藏您的代码已经变成意大利面条的事实。使所有这些相互依赖变得更容易只是掩盖了潜在的潜在问题。
  • 您无法轻松管理自己的“工作单元”,因为您无法管理跨多个依赖项的事务,因为您无法控制实例化它们并在该事务的上下文中传递。

Don't get me wrong, I love dependency injection and the inversion of control principle, but I think the IOC container could be used responsibly, but just be aware of the battles that you will need to fight because of the above list.

不要误会我的意思,我喜欢依赖注入和控制反转原则,但我认为 IOC 容器可以负责任地使用,但请注意由于上述列表而需要进行的战斗。