如何避免出现InvalidCastException异常?

3

我有一个扩展方法,多年来在WinForms中使用过,但是在尝试在新的WPF项目中使用时遇到了问题。该方法:

public static String GetDescription(this Enum value)
{
    //var info = value.GetType().GetField(value.ToString());
    //if (info != null)
    //{
    //    var attributes = (DescriptionAttribute[])info.GetCustomAttributes(typeof(DescriptionAttribute), false);
    //    if (attributes != null && attributes.Length > 0)
    //        return attributes[0].Description;
    //}
    //return value.ToString();

    var info = value.GetType().GetField(value.ToString());
    var attributes = Attribute.GetCustomAttributes(info);
    if (attributes.Length > 0 && (attributes[0] is System.ComponentModel.DescriptionAttribute))
        return ((System.ComponentModel.DescriptionAttribute)attributes[0]).Description;
    return value.ToString();
}

第一个块(被注释掉的)是原始方法。第二个块是我正在测试的稍微不同的版本。如果我强制执行带有转换的返回行,那么会出现此异常:

InvalidCastException image

该对话框中异常的完整文本如下:
附加信息: [A]System.ComponentModel.DescriptionAttribute 无法强制转换为[B]System.ComponentModel.DescriptionAttribute。类型A源自'System.ComponentModel.Primitives,Version=4.1.1.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a',位于'C:\TFS_Local\Antero\AnteroWPF\bin\Debug\System.ComponentModel.Primitives.dll'上下文中的“默认”位置。类型B源自“System,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089”在'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll'上下文中的“默认”位置。
涉及到的两个程序集似乎是:
System.ComponentModel.Primitives.dll(存在于构建bin目录中...不太确定它是如何到达那里的)
System.dll(出于明显的原因直接从GAC引用)

我完全迷失了。如果我移除ComponentModel DLL,那就会产生异常。即使异常声称System具有该类型,似乎也无法使用它。也就是说,在没有相应DLL的情况下,System.ComponentModel.DescriptionAttribute似乎不是有效的操作。

因此,如果我删除其中一个并失败了,而另一个则完全无法使用...那么为什么会出现这种异常?!

编辑: 我认为值得注意的是,如果我检查内存中的attributes值,我会发现数组确实有一个单一项,并且它是System.ComponentModel.DescriptionAttribute类型。


带有转换的那一行 - DonBoitnott
这对我来说很好用:https://github.com/heldersepu/csharp-proj/commit/c80e3e9828cb08c11cd17031fa10e6a4852878da#diff-225b67798e354b1ad8b608f72aa1ded5 - Helder Sepulveda
@HelderSepu 虽然你的示例实际上是不完整的(你的枚举值没有描述属性),但它在那种简单的形式下确实有效。不幸的是,这并没有让我看清楚其中的区别。 - DonBoitnott
@DonBoitnott,您能提供一个完整的示例吗? - Helder Sepulveda
这里我为您开始了一个:http://rextester.com/TYUY61604 - Helder Sepulveda
2个回答

2
如果我移除ComponentModel DLL,那么引发异常的就是它。你所遇到的异常非常明显:你的项目引用了两个不同的程序集,这两个程序集都定义了相同的类型System.ComponentModel.DescriptionAttribute。这个类型被文档记录在System.dll中。因此,System.ComponentModel.Primitives.dll程序集似乎是罪魁祸首。一番网络搜索后,我找到了这个System.ComponentModel.Primitives NuGet包。根据描述,它似乎与.NET Core有关,并且在.NET Core源代码中有该类型的实现。
在编译时,程序集似乎已经放置在您的构建目录中,即C:\TFS_Local\Antero\AnteroWPF\bin\Debug。那么问题来了,如果您正在构建一个 WPF 程序,为什么您的构建目录中有一个 .NET Core 程序集呢?您是否在某个时候安装了 NuGet 包?您的构建目录包括根目录 TFS_Local,这暗示您可能已加入 Team Foundation Server 存储库。有可能是同事为您的构建安装了该包吗?
我没有看到任何迹象表明您可以混合使用桌面版 .NET Framework 和 .NET Core。因此,简短的答案对我来说似乎只是“不要这样做”。如果没有引用 System.ComponentModel.Primitives.dll 程序集,您可能会遇到其他错误,但您需要以其他方式解决这些错误。我不知道有任何理由相信您应该能够使用 .NET Core DLL 编译桌面 WPF 程序。
如果你持有不同意见,那么请解释一下为什么你认为可以在 WPF 程序中使用 .NET Core 组件,你具体是如何做到这一点的,并且采取了哪些步骤确保在 .NET Core 中声明的类型不会与桌面 .NET Framework 组件(包括 System.dll)中声明的类型发生冲突。

最终,你猜测另一个团队成员做出了更改的想法是正确的。提供枚举的程序集被制作为“可移植”的,以便与移动项目一起使用,这导致原始 DLL 被吸入,从而导致异常(以及我对它如何到达那里的困惑)。 - DonBoitnott

0

为了解决这个问题,清空你的 bin 和 obj 文件夹。并将从 GAC 引用的引用对象的“复制本地”设置为 false。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接