4

public abstract class CompositionPlugin { ... }

public class MyCompositionPlugin : CompositionPlugin { ... }

我想检查一个对象的类型是否等于给定的类型:

public class Framework {

    public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>();

    public CompositionPlugin GetCompositionPlugin(Type ofType)
    {
        foreach (CompositionPlugin plugin in CompositionPlugins)
        {
            if (plugin.GetType().Equals(ofType))
                return plugin;
        }

        throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
    }
}

该方法的调用方式如下:

Framework framework = new Framework();
// Adding the plugin to the framework is done by loading an assembly and
// checking if it contains plugin-compatible classes (i.e. subclasses
// of <CompositionPlugin>)
framework.RegisterAssembly("E:\\Projects\\Framework\\MyPlugin\\bin\\Debug\\MyPlugin.dll");
CompositionPlugin plugin = framework.GetCompositionPlugin(typeof(MyCompositionPlugin));

然而,在测试时,这个检查总是失败,即使我在我请求的列表中肯定有那种类型的对象。

据我了解,它应该返回在-ListMyCompositionPlugin中找到的第一个实例。CompositionPlugins

我的类型检查错了吗?为什么?它是如何正确完成的?

4

5 回答 5

8

您想IsAssignableFrom在您的类型上使用:

if (ofType.IsAssignableFrom(plugin.GetType())

Equals仅处理类型完全相同的情况。IsAssignableFrom还处理ofType可能是插件继承的类型或实现的接口的情况。

于 2012-08-01T14:16:33.880 回答
5

不是答案,但评论太长了...您确定问题不在于您如何调用该方法或填充您的集合吗?比较本身应该没问题,正如您的代码的简化版本所示:

class A {}

bool TestType(A item, Type ofType)
{       
    return item.GetType().Equals(ofType);
}

现在:

Console.WriteLine(TestType(new A(), typeof(A))); // True
Console.WriteLine(TestType(new A(), typeof(string))); // False

编辑

我认为@vcsjones 是对的。您正在尝试将派生类与基类进行比较。在foreach (CompositionPlugin plugin in CompositionPlugins)您将插件声明为 CompositionPlugin 的行中,但在客户端代码中您将其与typeof(MyCompositionPlugin). (重新编辑不,我错了,你的情况对应于我的第 4 个Console.WriteLine返回 true)

在与您的情况类似的情况下,请参阅带有 Equals 真值表的示例:

class CompositionPlugin {}
class MyCompositionPlugin : CompositionPlugin  {}

// Define other methods and classes here
bool TestType(CompositionPlugin item, Type ofType)
{       
    return item.GetType().Equals(ofType);
}

现在

Console.WriteLine(TestType(new CompositionPlugin(), 
            typeof(CompositionPlugin))); //True
Console.WriteLine(TestType(new CompositionPlugin(), 
            typeof(MyCompositionPlugin))); //False
Console.WriteLine(TestType(new MyCompositionPlugin(), 
            typeof(CompositionPlugin))); //False
Console.WriteLine(TestType(new MyCompositionPlugin(),
            typeof(MyCompositionPlugin))); //True
于 2012-08-01T14:27:04.503 回答
3

使用关键字is

if (plugin is ofType)
    return plugin;

编辑:

我必须和@vcsjones 一起去这个。使用isassignablefrom函数。

但如果你真的认为它应该工作,我总是做的是创建快速函数来将调试文本写入文件。

public class Framework {

    public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>();

    public CompositionPlugin GetCompositionPlugin(Type ofType)
    {
        using(var writer = System.IO.File.CreateText(@"C:\test.log"))
        {
            writer.WriteLine("ofType: " + ofType.toString());
            foreach (CompositionPlugin plugin in CompositionPlugins)
            {
                writer.WriteLine("plugin: " + plugin.GetType().toString());
                if (plugin.GetType().Equals(ofType))
                    return plugin;
            }
        }

        throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
    }
}
于 2012-08-01T14:13:18.513 回答
0

事实证明,我最初忽略的信息,认为它不重要,毕竟如此。

和都定义在不同的程序集中,执行程序在运行时动态加载MyCompositionPluginCompositionPlugin

.NET-Runtime 现在考虑从不同程序集加载的类型,而不是执行程序集引用的类型,从而将MyCompositionPlugin-Type 中的 -TypeProgram视为不等于MyCompositionPlugin从另一个程序集加载,即使它们实际上是相同的。

比较两者是否相等(因为它们在常识中是相同的“类”)的解决方案是将其分解为定义程序集的字符串相等性,这可以说是肮脏的,但可以解决问题。

public CompositionPlugin GetCompositionPlugin(Type ofType)
{
    foreach (CompositionPlugin plugin in CompositionPlugins)
        if (ofType.AssemblyQualifiedName.Equals(plugin.GetType().AssemblyQualifiedName))
            return plugin;

    throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
}

感谢Paolo Falabella指出这个问题

于 2012-08-03T07:09:19.247 回答
0

您的问题很可能是由于第二次加载程序集并因此相等失败,最好避免再次加载程序集,因此您可以使用普通类型比较而不是需要使用脏字符串比较。我有同样的问题,我的插件接口是在一个单独的程序集中定义的,这个程序集存在于启动文件夹中,但也存在于插件文件夹中,插件程序集从该文件夹中动态加载,因此接口类型相等失败。我从插件文件夹中删除了接口 dll,之后一切都按预期工作。

于 2015-04-01T07:05:36.810 回答