InvalidCastException приведение объекта к своему собственному типу - PullRequest
3 голосов
/ 09 октября 2010

Я в настоящее время полностью сбит с толку проблемой, с которой я столкнулся. Я пишу плагин для другого приложения, которое предоставляет общедоступный .NET API. Я создал класс с именем Room и использую PropertyGrid, чтобы пользователи могли видеть и редактировать свойства экземпляров Room. Некоторые свойства ограничены набором стандартных значений. Поэтому я использую пользовательские TypeDescriptors с переопределениями GetStandardValues(), чтобы сетка свойств показывала раскрывающийся список для этих свойств.

Это все работало просто отлично. Я получал выпадающие списки, и я мог редактировать значения без проблем. Тем не менее, по какой-то причине, когда я выбираю Room, PropertyGrid показывает свойства с дескрипторами типа в виде черного ящика.

alt text

Если я нажму на поле, оно станет белым, и у меня появится мигающий курсор, но я ничего не могу напечатать. Если я затем выберу другую комнату, моя программа аварийно завершит работу со следующим исключением:

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. Кто-нибудь знает, что происходит?

Ответы [ 2 ]

1 голос
/ 09 октября 2010

Если трассировка стека всегда показывает одну и ту же строку, даже после того, как вы изменили код, который будет указывать мне, что ProperyGrid не выполняет ту же версию сборки. Это еще раз подтверждается, когда вы говорите, что ставите точку останова, но точка останова никогда не срабатывает. Если вы работаете в отладчике для Visual Studio, я предлагаю вам взглянуть на окно вывода (Ctrl + W, O), в котором будет показан список всех сборок (с указанием их пути), которые были загружены во время выполнения. Я видел путаницу версии сборки, особенно когда сборка находится в GAC, где она настаивает на загрузке более старой версии сборки.

0 голосов
/ 09 октября 2010

Может случиться так, что два типа на самом деле различаются - например, если один из них загружен из другой версии какой-либо сборки, чем другой тип.Я не совсем уверен, может ли это произойти в вашем случае, но это может быть проблемой.

Самый простой способ проверить это - установить точку останова в месте, где выдается исключение.Затем вы можете посмотреть на два типа в часах или в ближайшем окне и посмотреть на o1.GetType().Assembly. FullName (и аналогично для другого объекта).

...