【问题标题】:Plugin Architecture with Interfaces; Interface check doesn't work带接口的插件架构;接口检查不起作用
【发布时间】:2010-11-19 04:03:29
【问题描述】:

我正在应用程序中实现一个简单的插件架构。插件要求是使用应用程序和插件引用的 *.dll 中的接口 (IPlugin) 定义的。该应用程序有一个插件管理器(也在同一个 *.dll 中),它通过在插件文件夹中查找所有 *.dll 来加载插件,加载它们,然后检查插件是否实现了接口。我已经通过两种不同的方式进行了此检查[以前通过简单的 if (plugin is IPlugin)],但是当插件实现接口时,没有人会识别。代码如下:

Assembly pluginAssembly = Assembly.LoadFrom(currFile.FullName);
if (pluginAssembly != null)
{
    foreach (Type currType in pluginAssembly.GetTypes())
    {
        if (currType.GetInterfaces().Contains(typeof(IPlugin)))
        {
            // Code here is never executing
            // even when the currType derives from IPlugin
        }
    }                    
}

我曾经测试一个特定的类名(“插件”),但后来我让它循环遍历程序集中的所有类,但无济于事。 (这遵循了我在其他地方找到的示例。) 为了使这更复杂一点,有两个接口,每个接口都实现了原始接口(IPluginA,IPluginB)。该插件实际上实现了更具体的接口之一(IPluginB)。但是,我已经尝试使用仅实现更通用接口(IPlugin)的插件,但仍然无法正常工作。

[编辑:回应我第一次收到的两个回复] 是的,我尝试过使用 IsAssignableFrom。请参阅以下内容:

Assembly pluginAssembly = Assembly.LoadFrom(currFile.FullName);
if (pluginAssembly != null)
{
    foreach (Type currType in pluginAssembly.GetTypes())
    {
        if (typeof(IPlugin).IsAssignableFrom(currType))
        {
            string test = "test";
        }
    }
}

【问题讨论】:

  • 更大的代码示例将有助于理解实际问题。我很确定 IsAssignableFrom 正在为我工​​作,正如我在我的应用程序中写的那样 - 完全符合预期。
  • 请检查 currFile 是否是包含插件的 DLL 并查看插件程序集中每种类型的 currType 是什么。
  • currFile包含插件的*.dll,currType是(程序集中唯一的类型),是一个实现IPlugin的Plugin。换句话说,这些都是正确的。还有其他想法吗?
  • 不应该是: if(currType.IsAssignableFrom(typeof(IPlugin)) 您正在测试 IPlugin 的类型是否可以从您的插件类型中分配。您应该测试您的类型是否插件可以从 IPlugin 分配吗?
  • Kristoffer, 280Z28 回复中的代码是正确的。我相信您应该考虑的方式是:我可以将类型的 istnace(即方法的参数)分配给 .IsAssignableFrom 之前的类型实例。 MSDN 文章说明了这几种不同的方式(可能在技术上比我做的更正确):msdn.microsoft.com/en-us/library/…

标签: c# interface plugin-architecture


【解决方案1】:

你试过了吗:

typeof(IPlugin).IsAssignableFrom(currType)

此外,类型实现接口,但它们不派生它们。 BaseType 属性和IsSubclassOf 方法显示派生,其中IsAssignableFrom 显示派生或实现。

编辑:您的程序集是否已签名?它们可能正在加载side-by-side versions of your assembly,并且由于将Type 对象与ReferenceEquals 进行比较,因此两个并排程序集中的相同类型将完全独立。

编辑 2: 试试这个:

public Type[] LoadPluginsInAssembly(Assembly otherAssembly)
{
    List<Type> pluginTypes = new List<Type>();
    foreach (Type type in otherAssembly.GetTypes())
    {
        // This is just a diagnostic. IsAssignableFrom is what you'll use once
        // you find the problem.
        Type otherInterfaceType =
            type.GetInterfaces()
            .Where(interfaceType => interfaceType.Name.Equals(typeof(IPlugin).Name, StringComparison.Ordinal)).FirstOrDefault();

        if (otherInterfaceType != null)
        {
            if (otherInterfaceType == typeof(IPlugin))
            {
                pluginTypes.Add(type);
            }
            else
            {
                Console.WriteLine("Duplicate IPlugin types found:");
                Console.WriteLine("  " + typeof(IPlugin).AssemblyQualifiedName);
                Console.WriteLine("  " + otherInterfaceType.AssemblyQualifiedName);
            }
        }
    }

    if (pluginTypes.Count == 0)
        return Type.EmptyTypes;

    return pluginTypes.ToArray();
}

【讨论】:

  • 我尝试过使用 IsAssignableFrom,但它也不起作用。请参阅我在原始问题中的编辑。
  • 我认为程序集没有签名 (GAC)。 OP 说,他正在尝试从插件文件夹中加载它。
  • 它们没有签名(不在 GAC 中)。
  • 什么?我根本没有说 GAC。我签署了我的程序集,但我无法将它们放入 GAC。
  • 没关系,只是想通了。对于其他人:右键单击引用并将 Copy-Local 更改为 false。
【解决方案2】:

IsAssignableFrom 方法就是您要寻找的方法:

Type intType = typeof(IInterface);
foreach (Type t in pluginAssembly.GetTypes())
{
    if (intType.IsAssignableFrom(t))
    {
    }
}

【讨论】:

  • 我尝试过使用 IsAssignableFrom,但它也不起作用。请参阅我在原始问题中的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 2022-08-17
  • 2013-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
相关资源
最近更新 更多