1

我以前在 C# 中为一个运行良好的插件系统做过这个,这就是为什么我对为什么这个新的、独立的插件系统没有按我期望的方式工作感到困惑。

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

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

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

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

是真的。我还可以MyObject在 Visual Studio 的对象资源管理器中浏览,我可以看到它实现了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

4 回答 4

3

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

于 2012-11-21T05:46:19.110 回答
2

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

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

于 2012-11-21T05:48:05.613 回答
1

.NET 中可扩展应用程序的典型骨架由以下程序集组成:

  • 合同组装。这个包含插件的合约(只是接口和可选的一些数据合约,用于接口)和主机合约;
  • 主机组装。这一个包含主机合同实现,并依赖于第一个;
  • 几个插件程序集。这些程序集包含插件契约实现,并且也依赖于第一个。

因此,使用合同组装,您可以实现主机和插件彼此独立(因此,插件后期绑定的),但它们具有共同的合同,在编译时双方(插件和主机)都知道。

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

于 2012-11-21T05:58:09.657 回答
1

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

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

于 2012-11-21T06:02:32.180 回答