【问题标题】:InvalidCastException casting object to its own typeInvalidCastException 将对象转换为自己的类型
【发布时间】:2010-10-09 00:24:41
【问题描述】:

我目前对我遇到的问题感到完全困惑。我正在为另一个提供公共 .NET API 的应用程序编写插件。我创建了一个名为Room 的类,并且我正在使用PropertyGrid 来允许用户查看和编辑Room 实例的属性。一些属性仅限于一组标准值。因此,我使用带有 GetStandardValues() 覆盖的自定义 TypeDescriptors 来获取属性网格以显示这些属性的下拉列表。

这一切都很好。我得到了下拉菜单,我可以编辑值没问题。但是现在由于某种原因,当我选择 Room 时,PropertyGrid 将带有类型描述符的属性显示为黑框。

如果我单击该框,它会变成白色,并且我会看到一个闪烁的光标,但我无法输入任何内容。如果我然后选择另一个房间,我的程序会崩溃并出现以下异常:

System.InvalidCastException was caught
  Message=Unable to cast object of type 'DVAMC.Room' to type 'DVAMC.Room'.
  Source=DVAMC
  StackTrace:
       at DVAMC.BuildingTypeConverter.GetStandardValuesSupported(ITypeDescriptorContext context) in C:\Documents and Settings\eric.anastas\My Documents\_SVN WC\DVAMC Working\BuildingTypeConverter.cs:line 14
       at System.Windows.Forms.PropertyGridInternal.GridEntry.get_Flags()
       at System.Windows.Forms.PropertyGridInternal.GridEntry.get_NeedsDropDownButton()
       at System.Windows.Forms.PropertyGridInternal.PropertyDescriptorGridEntry.get_NeedsDropDownButton()
       at System.Windows.Forms.PropertyGridInternal.PropertyGridView.SelectRow(Int32 row)
       at System.Windows.Forms.PropertyGridInternal.PropertyGridView.SelectGridEntry(GridEntry gridEntry, Boolean fPageIn)
       at System.Windows.Forms.PropertyGridInternal.PropertyGridView.GridPositionData.Restore(PropertyGridView gridView)
       at System.Windows.Forms.PropertyGridInternal.PropertyGridView.Refresh(Boolean fullRefresh, Int32 rowStart, Int32 rowEnd)
       at System.Windows.Forms.PropertyGridInternal.PropertyGridView.Refresh()
       at System.Windows.Forms.PropertyGrid.Refresh(Boolean clearCached)
       at System.Windows.Forms.PropertyGrid.set_SelectedObjects(Object[] value)
       at System.Windows.Forms.PropertyGrid.set_SelectedObject(Object value)
       at DVAMC.RoomDetailsForm.set_RoomDetailsSelectedRoom(Room value) in C:\Documents and Settings\eric.anastas\My Documents\_SVN WC\DVAMC Working\RoomDetailsForm.cs:line 115
       at DVAMC.RoomDetailsForm.roomListTreeView_SelectionChanged(Object sender, EventArgs e) in C:\Documents and Settings\eric.anastas\My Documents\_SVN WC\DVAMC Working\RoomDetailsForm.cs:line 159
       at BrightIdeasSoftware.ObjectListView.OnSelectionChanged(EventArgs e)
       at BrightIdeasSoftware.ObjectListView.HandleApplicationIdle(Object sender, EventArgs e)
       at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.RunDialog(Form form)
       at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
       at System.Windows.Forms.Form.ShowDialog()
       at DVAMC.RoomDetailsCmd.Execute(ExternalCommandData commandData, String& message, ElementSet elements) in C:\Documents and Settings\eric.anastas\My Documents\_SVN WC\DVAMC Working\RoomDetailsCmd.cs:line 44
  InnerException: 

堆栈跟踪中的最后一项指向我的 BuildingTypeConverter.GetStandardValuesSupported() 方法,如下所示。

GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context)
{
    Room r = (Room)context.Instance; //this is line 14 referenced by the InvalidCastException's stack trace

    if (r.IsLinked)
    {
        return true;
    }
    else
    {
        return false;
    }
}

现在,如果我在上面的第 14 行设置断点并尝试调试,调试器不会在断点处中断。此外,如果我在强制转换之前添加任意代码,来自 InvalidCastException 的堆栈跟踪似乎总是引用 GetStandardValues() 的第一行,无论它是什么。例如,我尝试了以下操作。

public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context)
    {
        string s = "hello world";   //FIRST LINE
        int i = 0;


        Room r = (Room)context.Instance; 

        .....

我仍然遇到同样的 InvalidCastException。然而它的堆栈跟踪引用了上面我初始化string s 的第一行。另外,如果我尝试在第一行设置断点,它也不会被触发。

就像我之前所说的,大约一天前工作得很好。我什至尝试在我的 SVN 存储库中回滚到以前的版本。我早在第一次修订时就创建了自定义类型描述符类,但仍然遇到InvalidCastExceptions 的问题。有人知道发生了什么吗?

【问题讨论】:

  • 我最近以类似的方式感到困惑,结果证明它与设计师生成的代码有关
  • 嗯,很有趣。然而对我来说,即使我回滚(包括设计器代码)到一个正在运行的版本,它仍然不起作用。不过,我确实有一些与我的类同名的属性。

标签: c# propertygrid .net typedescriptor


【解决方案1】:

如果堆栈跟踪始终显示同一行,即使您更改了代码,这表明 ProperyGrid 没有运行相同版本的程序集。当你说你放置了一个断点但断点从未被命中时,这一点得到了进一步的证实。如果您在 Visual Studio 的调试器中运行,我建议您查看输出窗口 (Ctrl+W, O),它将列出运行中加载的所有程序集(及其路径)。我看到程序集版本混乱,特别是当程序集在 GAC 中时,它坚持要加载旧版本的程序集。

【讨论】:

  • 是的,我不知道为什么,但在根程序文件夹中有我的 DLL 文件的单独副本。奇怪的是我的代码似乎同时引用了两者。例如,我可以在 SelectionChanged 事件处理程序中捕获断点,但在我在那里设置 PropertyGrid.SelectedObject 属性后,它不会在 GetStandardValues() 方法中捕获断点。我删除了额外的 DLL 副本,它再次完美运行。谢谢!
【解决方案2】:

这可能是这两种类型实际上不同 - 例如,如果其中一种是从某个程序集的另一个版本而不是另一种类型加载的。我不太确定您的情况是否会发生这种情况,但这可能是个问题。

检查这一点的最简单方法是将断点放置在引发异常的位置。然后您可以在手表或即时窗口中查看这两种类型,然后查看o1.GetType().Assembly. FullName(对于其他对象也是如此)。

【讨论】:

    猜你喜欢
    • 2019-12-24
    • 2020-12-02
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多