代码之家  ›  专栏  ›  技术社区  ›  TheCloudlessSky

在不创建实现的情况下实现接口(动态代理?)

  •  2
  • TheCloudlessSky  · 技术社区  · 14 年前

    我一直在努力创建自己的IOC容器,以供学习之用。在问了几个关于它们的问题之后,我发现创建一个工厂来“解决”对象是最好的解决方案。( see third solution here )用户 Krzysztof Koźmic 显示了温莎城堡实际上可以为你实现这一点。

    我一上午都在读《化学武器》的出处。我知道当调用resolve时,它会“返回接口”。这个接口如何“拦截”调用(因为后面没有实现)并调用它 拥有 方法?

    我知道很明显这里有一些反射的诡计,这很神奇。我根本不是“截取”的用户。我试着自己在吉特的兔子洞里冒险,但我迷路了。如果有人能给我指明正确的方向,我将不胜感激。

    另外-创建类型化工厂是否会依赖调用代码中的容器?在ASP.NET MVC术语中,我就是这么认为的。

    编辑:找到 Reflection.Emit …这是用过的吗?

    伊迪丝2:我研究得越多,自动创建工厂听起来就越复杂。我可能最终只会坚持重复的代码。

    3 回复  |  直到 13 年前
        1
  •  7
  •   Dan Bryant    14 年前

    这里有两个独立的概念:

    1. 依赖注入只实例化实现接口的现有类。例如,您可能有一个实现imyservices的myServices类。IOC框架为您提供了各种方法来指定当您请求一个imyservices时,它将解析为一个myservices实例。可能会有一些il emit magic继续设置factory或helper方法,但实际的实例只是您定义的类。

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


    更详细地说,您实际上不需要使用IL来实现IOC功能,但这对于避免重复反射调用的开销通常很有价值,因为反射相对昂贵。 Here 是温莎城堡正在做什么的一些信息。


    为了回答你的问题,我发现最有帮助的地方是 OpCodes 班级。这是对IL中可用功能以及操作码如何工作的一个很好的总结。它本质上是一种基于堆栈的汇编语言(不需要担心寄存器),但是它是强类型的,并且具有对对象符号和概念(如类型、字段和方法)的一流访问。 Here 是一篇介绍IL基础知识的优秀代码项目文章。如果您感兴趣,我还可以向您发送一些我在过去几年中创建的用于我自己的emit代码的助手类。

        2
  •  5
  •   Krzysztof Kozmic    14 年前

    类型化工厂是使用castle dynamicproxy库实现的。它动态生成一个实现接口的类型,并将通过接口所做的所有调用转发给拦截器。

    它在代码中不施加依赖性。该接口是在您的程序集中创建的,您可以在其中不引用windsor。在另一个组件(应用程序的入口点)中,你告诉温莎这个接口,并告诉它成为一个工厂,温莎了解你的接口,并用它做一些事情。这是对其荣耀的颠覆。

    其实没那么复杂:)

        3
  •  1
  •   jbtule    13 年前

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