2

我一直在为创建目的而创建自己的IoC容器。在问了一些有关它们的问题后,我发现创建一个工厂来“解决”这些对象是最好的解决方案(see third solution here)。用户Krzysztof Koźmic表明,温莎城堡实际上可以为你实现这一点。在没有创建实现的情况下实现接口(动态代理?)

我一直在读清楚CW的来源。我知道Resolve何时被调用,它“返回接口”。这个接口如何“截取”调用(因为后面没有实现)并将其称为自己的方法?

我知道这里显然有一些反思技巧,这真是太神奇了。我完全不知道“拦截”是如何完成的。我尝试在git上冒险尝试兔子洞,但我迷路了。如果任何人都能指出我正确的方向,那将非常感激。

此外 - 不会创建一个类型的工厂具有对调用代码内的容器的依赖?在ASP.NET MVC术语中,这就是我所认为的。

编辑:找到Reflection.Emit ...这可能是什么用?

EDIT2:我越看越这个,自动创建工厂听起来越复杂。我可能最终只是坚持重复的代码。

回答

7

这里有两个不同的概念:

  1. 依赖注入仅实例化一个现有的类实现接口。例如,您可能有一个实现IMyServices的MyServices类。 IoC框架为您提供了多种方式来指定当您请求IMyServices时,它将解析为MyServices的一个实例。可能会有一些IL Emit魔法继续建立工厂或辅助方法,但实际实例只是您定义的类。

  2. Mocking允许您实例化一个实现接口的类,而实际上不必编写该类。正如你所想的那样,这通常会利用Reflection和IL Emit。通常,发布的IL代码非常简单,将大部分工作委托给用C#编写的方法。模拟的大部分复杂性与指定方法本身的行为有关,因为框架通常允许您使用流畅的语法指定行为。有些像Moles,只是让你指定一个委托来实现该方法,尽管Moles可以做其他更疯狂的事情,比如将调用重定向到静态方法。


为了进一步详细一点,你实际上并不需要使用IL来实现的IoC功能,但是这往往是宝贵的,以避免重复反射调用的开销,因为思考是比较昂贵的。 Here是关于Castle Windsor正在做什么的一些信息。


要回答你的问题,最有用的地方,我发现开始是OpCodes类。这是对IL中可用功能和OpCodes功能如何的一个很好的总结。它基本上是一个基于堆栈的汇编语言(不需要担心寄存器),但是强类型化并且具有一流的对象符号和概念访问权限,例如类型,字段和方法。 Here是一个很好的代码项目介绍IL的基础知识。如果您有兴趣,我还可以向您发送一些我在过去几年中创建的助手类,这些助手类用于自己的发射码。

+0

感谢您的评论。我正在尝试*使用*“嘲笑”我尝试制作的IoC容器。温莎城堡使用某种技术来创建一个实现指定界面的“类型工厂”。如果您阅读我从Krzysztof发布的链接,您会明白我的意思。我不想使用第三方库,因为这些都是为了我自己的学习。你有没有关于课堂生成的任何资源?编辑:我知道我不需要*使用IL,我只是好奇它是如何完成的。谢谢! :) – TheCloudlessSky 2010-07-05 15:26:15

+0

谢谢你。我要开始阅读。我可能不会实现这个功能,因为它看起来非常极端。但是,我要去看看这个,因为它非常有趣。谢谢! – TheCloudlessSky 2010-07-05 15:39:39

+0

@ TheCloudlessSky,IL很有趣,因为你可以用它做一些非常强大的事情。但是它的确需要很多工作,而且Emit方法是非常自然的(它们不提供任何包含正确参数的检查,因此很容易错误地创建IL代码,而这些代码在运行时无法验证或爆炸。 )如果你使用它,只要记住peverify.exe是你的朋友。 – 2010-07-05 15:44:52

5

输入的工厂使用Castle DynamicProxy库实现。它会动态地生成一个类型来实现接口,并将所有调用转换为该类型,通过接口转发给拦截器。

它不会在您的代码中产生依赖关系。该界面在您的装配体中创建,由您控制,您不参考Windsor。在其他程序集(应用程序的入口点)中,您告诉Windsor该界面,并告诉它使其成为工厂,并且Windsor了解您的界面并使用它进行操作。这是控制的倒戈,它的荣耀。

它其实没有那么复杂:)

+0

感谢您的回答。那么,我认为Castle DynamicProxy库使用Reflection.Emit? – TheCloudlessSky 2010-07-05 22:32:15

+0

没关系。我去挖掘DynamicProxy的源代码,发现了各种各样的整洁的东西(是的,它使用了Reflection.Emit)。谢谢! :) – TheCloudlessSky 2010-07-05 22:40:02

1

ImpromptuInterface创建基于接口的DLR动态代理。它允许您使用静态接口进行动态实现。事实上,它甚至有一个基类ImpromptuFactory,它提供了基于接口创建工厂动态实现的起点。

相关问题