【问题标题】:C# cast a class to an Interface ListC# 将类强制转换为接口列表
【发布时间】:2012-08-05 18:53:14
【问题描述】:

我正在尝试动态加载一些 .dll 文件。文件是插件(目前是自己编写的),其中至少有一个实现MyInterface 的类。对于每个文件,我都在执行以下操作:

    Dictionary<MyInterface, bool> _myList;

    // ...code

    Assembly assembly = Assembly.LoadFrom(currentFile.FullName);
    foreach (Type type in assembly.GetTypes())
    {
        var myI = type.GetInterface("MyInterface");
        if(myI != null)
        {
            if ((myI.Name == "MyInterface") && !type.IsAbstract)
            {
                var p = Activator.CreateInstance(type);
                _myList.Add((MyInterface)p, true);
            }
        }
    }

运行它会导致转换异常,但我找不到解决方法。无论如何,我想知道为什么这根本不起作用。我正在寻找 .NET Framework 3.5 中的解决方案。

发生在我身上的另一件事是在上面的代码中向_myList 添加新条目之前运行以下命令后,在p 中获得了null:

var p = type.InvokeMember(null, BindingFlags.CreateInstance, null,
                          null, null) as MyInterface;

这段代码是加载插件的第一次尝试,我还没弄清楚为什么p 是null。 我希望有人能引导我走向正确的道路:)

【问题讨论】:

  • 这段代码不起作用,x 是什么以及你在哪里初始化它?
  • 在上面的代码 sn-p 中,“if (x !=null)”中的“x”真的应该是“myI”吗?
  • 您还应该验证该类型是否具有默认构造函数,因为您的代码假定了这一点。
  • 我不明白var myI = type.GetInterface("MyInterface"); if(x != null)。应该是if (myI != null)?
  • Activator.CreateInsance(type) 假定存在您的类型的无参数构造函数。你得到什么样的例外?如果是MissingMethodException,问题(几乎可以肯定)是您的类没有无参数构造函数。

标签: c# interface casting invoke


【解决方案1】:

有更简单的方法来检查您的类型是否可以转换为您的界面。

Assembly assembly = Assembly.LoadFrom(currentFile.FullName);
foreach (Type type in assembly.GetTypes())
{
    if(!typeof(MyInterface).IsAssignableFrom(type))
        continue;

    var p = Activator.CreateInstance(type);
    _myList.Add((MyInterface)p, true);
}

如果IsAssignableFrom 为假,则说明您的继承有问题,这很可能是您的错误的原因。

【讨论】:

  • 是的,它是false。但是我现在只有一个成员,真的不知道继承有什么问题。
  • 您的“插件”程序集是否引用了定义接口的程序集?您的运行代码(示例代码)是否引用 same 程序集?
【解决方案2】:

您真的应该阅读 Jon Skeet 的 Plug-ins and cast exceptions,它解释了您看到的行为以及如何正确地执行插件框架。

【讨论】:

  • 我可以从中得到的是插件的程序集与我的应用程序的程序集不同。
  • 我希望更多的人会投票赞成这个,因为我认为这可能是 OP 的问题。基本上,如果您将其视为 C++,而将接口定义视为 .h 文件,您将遇到此错误。如果您以“托管类型”的方式考虑它,您会看到有两个接口,每个文件一个,如果它的编译方式(错误)链接可能是这样。
【解决方案3】:

请查看以下代码。我认为Type.IsAssignableFrom(Type type) 可以在这种情况下帮助您。

Assembly assembly = Assembly.LoadFrom(currentFile.FullName);
///Get all the types defined in selected  file
Type[] types = assembly.GetTypes();

///check if we have a compatible type defined in chosen  file?
Type compatibleType = types.SingleOrDefault(x => typeof(MyInterface).IsAssignableFrom(x));

if (compatibleType != null)
{
    ///if the compatible type exists then we can proceed and create an instance of a platform
    found = true;
    //create an instance here
    MyInterface obj = (ALPlatform)AreateInstance(compatibleType);

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-23
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    相关资源
    最近更新 更多