是否可以在运行时为对象分配接口?

时间:2010-08-03 12:21:25

标签: .net design-patterns oop interface

在反映了我收到的previous question about modeling my code to maximize code re-use所有重要答案后,我开始想知道是否可以在运行时将接口分配给对象,而不是在编码时。

例如,来自my previous question的简化代码部分:

public class OutboxManager
{
    private IVendorMessenger _VendorMessenger;

    //This is the default constructor, forcing the consumer to provide
    //the implementation of IVendorMessenger.
    public OutboxManager(IVendorMessenger messenger)
    {
         _VendorMessenger = messenger;
    }

    public void DistributeOutboxMessages()
    {
        VendorMessenger.SendMessageToVendor()
                      _OutboxMgrDataProvider.MarkMessageAsProcessed(om)
    }

}

目前,如果有人想要使用这个类,他们必须编写一个实现IVendorMessenger的类,并在初始化期间将其作为参数提供:

 var MyOutboxManger = new OutboxManager(new MyVendorMessenger())

如果不是对接口参数进行硬编码,而是在运行时得到它,那该怎么办呢?这样,我可以为实现IVendorMessenger的类编译一个dll,将其放到OutboxManagerExecutable存在的同一文件夹中,它将在运行时连接所有内容。我想,使用这个逻辑,我可以找到一种方法来删除同一文件夹中的{em>多个实现IVendorMessenger,并将可执行文件设计得足够聪明,以便遍历所有适当的dll并消耗他们因此。

这种功能在.NET 4中是否可行?

5 个答案:

答案 0 :(得分:4)

查看Managed Extensibility Framework (MEF)。它可以像您描述的那样自动组成应用程序的依赖关系。它随.NET 4.0一起提供。

答案 1 :(得分:2)

这是一个非常常见的反射用例。 .NET API为您提供了所需的部分:

  1. 查找目录中的所有.dll:Directory.GetFiles()
  2. 在运行时加载这些程序集:Assembly.LoadFile()
  3. 遍历每个程序集中的类型:Assembly.GetTypes()
  4. 对于每种类型,请查看它是否实现了您的界面:Type.IsAssignableFrom()
  5. 如果是,请获取并调用其构造函数以创建一个:Type.GetConstructor()
  6. 之后,您有一个Object可以投射到IVendorMessenger并传入。

答案 2 :(得分:1)

您考虑使用MEF吗?它允许您创建许多模块的应用程序构建。

你可以看到它here

答案 3 :(得分:1)

编辑:我刚才意识到我误解了这个问题。实际上,问题 not 似乎是关于在运行时为对象分配接口,而是关于后期绑定类型名称。

我会将答案保留为社区维基,以防其他人有同样的误解。


这通常称为接口注入,并且只要它们存在就一直位于CLI和JVM的心愿单上。

特别是那些为CLI或JVM本身设计的编程语言编写实现的人,如JRuby,XRuby,Ruby.NET,IronRuby,IronPython,Jython,Rhino,IronJS等,都具备这一特性。他们的愿望清单,因为这意味着他们不再需要维护并行类型层次结构并在两者之间来回编组对象。

然而,它们似乎不会很快出现,或者确实根本没有出现,尽管至少有一个关于JVM的草编规范以及Da Vinci Machine的部分原型实现。

答案 4 :(得分:1)

你应该可以在 .Net 2.0 / 3.0 Generics中做到这一点(类别明智)。

您也可以使用Reflection to load a dll during runtime