如何从DLL访问具有接口的类?

时间:2017-02-21 19:44:39

标签: c# type-conversion dynamic-programming

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

主机使用此代码加载插件

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 Framework引发此异常:

  

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException   'System.ValueType'不包含'FileName'

的定义

然而,FileName字段在结构中是硬编码的,当然不是null或

  

Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException   绑定动态操作时发生意外异常

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

WTF?

1 个答案:

答案 0 :(得分:1)

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

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

  1. 让您的插件引用IKrotAPI接口的主机程序集。
  2. 仅针对主机和服务器通用的接口和数据类型(例如KrotAPI.FindData)创建第三个程序集。
  3. 我个人更喜欢第二种方法。它允许您升级主机程序集而不会使现有插件失效。要为这种程序集使用通用命名约定,可以将此第三个程序集称为KrotAPI。我倾向于将“API”视为某人(即插件开发人员)编写的接口和数据类型集,但在您的情况下,所有实际的可运行代码都将位于主机或插件中。 / p>