C#中的接口和后期绑定

时间:2012-11-21 05:38:06

标签: c# plugins interface late-binding .net

我之前在C#中已经完成了这个插件系统工作正常,这就是为什么我很困惑为什么这个新的,独立的插件系统没有按照我期望的方式工作。

我有我的插件程序集 - 让我们称它为“plugin.dll”,我有我的主程序集 - 让我们称之为App.exe。

我有一个名为IMyObject的接口及其实现MyObject,两者都在plugin.dll中定义。我已将IMyObject(插件开发者提供给我的)的确切代码文件复制到我的主App.exe程序集中。

当我尝试使用反射将对象加载到对象实现的接口时,我得到InvalidCastException。我知道该对象实现了它,因为

t.GetInterface(typeof(IMyObject).FullName) != null

是真的。我还可以在Visual Studio中的对象资源管理器中浏览MyObject,我可以看到它实现了IMyObject

这是出错的地方:

 if (ifaceType != null)
 {
    ConstructorInfo constructor = ifaceType.GetConstructor(new Type[] { });

    if (constructor != null)
    {

       object obj = constructor.Invoke(null); // this works - obj is assigned an 
                                              // instance of MyObject

       IMyObject myObj = (IMyObject)obj;      // triggers InvalidCastException
    }               
 }

我现在正在做的和我之前实现的方式之间的唯一区别是接口是在两个单独的程序集中定义的(即使代码文件是相同的,它们属于同一名称空间。)

这是我遇到麻烦的原因吗?如果是这样,如何在编译时连接到我的插件而不进行链接,并使用插件本身定义的接口?

我应该在接口之外添加它,我无法访问插件的源代码。

4 个答案:

答案 0 :(得分:3)

即使这些接口具有相同的代码,它们也是两个不同程序集中的两个独立接口(您可以打印它们的AssemblyQualifiedNames并查看差异)。

答案 1 :(得分:2)

是的,运行时将接口视为不同的类型。它们具有相同的名称。

没有反射就无法在主机程序中使用该接口,因为您无法静态链接它。通常,将接口放在插件主机程序集中,插件实现它们,而不是相反。

答案 2 :(得分:1)

.NET中可扩展应用程序的典型框架包含以下程序集:

  • 签订合同。这个包含插件的合同(只是接口和接口中使用的一些数据合同)和主机合同;
  • 主机装配。这个包含主机合同实现,并取决于第一个;
  • 几个插件程序集。这些程序集包含插件契约实现,也取决于第一个。

因此,使用契约汇编,您实现了主机和插件彼此独立(因此,插件 后期绑定),但它们具有共同的契约,在编译时已知双方的时间(插件和主持人)。

你的方式(多次定义插件联系人)是错误的方法。

答案 3 :(得分:1)

正如其他人所说,这些是单独的接口,处理这个问题的正确方法是将定义放入第二个引用的程序集中。

但是......有一种方法可以通过使用名为Impromptu Interface的库来实现这一点。