2017-02-21 71 views
2

我正在开发一个使用插件的程序。所有插件都是从KrotAPI.IKrotAPI接口继承的类。该接口存储在krotapi.cs文件中,这对于主机的csproj和每个插件的* .csproj都是通用的。如何从DLL接口访问类?

使用此代码

dynamic LoadPlugin(Assembly asm) 
{ 
    foreach (Type type in asm.GetTypes()) 
    { 
    if (type.GetInterface("KrotAPI.IKrotPlugin") != null) 
    { 
     PluginType = type; 
     dynamic inst = Activator.CreateInstance(type); 
     KrotAPI.IKrotPlugin inst2 = inst as KrotAPI.IKrotPlugin; 
     if (inst2 == null) return inst; 
     Console.WriteLine("Link to API is set up."); 
     return inst2; 
    } 
    } 
    throw new Exception("There are no valid plugin(s) in the DLL."); 
} 

inst2主机信息加载插件永远是空的,我被迫使用慢速和马车动态调用。如何使它像inst,但与KrotAPI.IKrotPlugin类型?


关于几乎相同的主题的第二个问题。 一些插件函数返回KrotAPI.FindData类型的结果(这是一个结构,存储在上面的krotapi.cs文件中)。但我不能访问它:

dynamic fd = new KrotAPI.FindData(); 
if (NextItemInfo != null) //NextItemInfo is an instance of that struct 
    fd = NextItemInfo; 
listBox1.Items.Add(fd.FileName); 

在最后一排.NET框架抛出此异常:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException “System.ValueType”不包含定义“文件名”

然而FileName字段在结构硬编码,肯定不是一个空,或

0123同时结合动态操作

如果我KrotAPI.FindData fd2 = (KrotAPI.FindData) fd; listBox1.Items.Add(fd2.FileName);替换最后一行出现

Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException 一个意外的异常。

WTF?

回答

1

您的主机和插件中已定义了IKrotAPI界面。这意味着它们不是相同的界面。包含的程序集是界面完整标识的一部分。每个插件实际上都实现了一个在自己的程序集中定义的接口,它与主机程序集中定义的接口不同。

有两种方法来解决这个问题:

  1. 让你的插件引用主机大会的IKrotAPI接口。
  2. 为接口和数据类型创建第三个程序集(例如KrotAPI.FindData),它们对于主机和服务器都是通用的。

我个人比较喜欢第二种方法。它允许你升级你的主机程序集而不会使现有的插件失效。为了对这种装配使用通用的命名约定,可以将这个第三个装配称为KrotAPI。我倾向于将“API”看作是某人(即插件开发人员)将编码的接口和数据类型集合,但是对于您的情况,所有实际可运行的代码都将位于主机或插件中。

+0

谢谢!当我选择第一种方式时可能会出现什么麻烦,并且一些插件会比主机exe更旧或更新?目前,我看到它更好,因为不需要在每个插件的目录中放置一个KrotAPI.dll文件,并且当插件目录中没有Krot.exe时,所有插件仍然可以正常工作(正如我假设的那样,插件正在使用已经加载到内存中的程序集)。 –

+0

程序集版本号是程序集标识的一部分,该标识随后成为界面标识的一部分。这意味着如果更新主机程序集的版本号,则该程序集定义的接口不再是插件程序集使用的接口。这可以通过绑定重定向来缓解。 –

+0

你不需要每个插件目录中的API程序集。如果你使用的是默认的AppDomain,你可以强制主机应用程序在加载任何插件之前加载API程序集,然后每个插件只使用已经加载的API程序集。你可以用多种方法强制装配装配(我通常使用空的静态方法)。如果你在单独的AppDomain中隔离你的每个插件,这是一个更多的工作,但你仍然可以让所有的插件使用一个中央API程序集。 –