2013-11-22 3 views
1

Я изо всех сил пытаюсь заставить эту иерархию работать с дженериками. Проблема в том, что элементы являются обобщенными, указанными на уровне наследования, поэтому я не могу отбросить обратно в BaseItem, то есть лить из SpecialItem (Of ExtraSpecialItem) в ItemHost (из BaseItem), когда SpecialItem наследует BaseGroup, поскольку BaseGroup реализует IItemHost.Кастинг Общий интерфейс к базовому типу

Что я здесь делаю неправильно?

Public MustInherit Class BaseItem 
    Public Property ItemNameOrSomething As String 
End Class 

Public Interface IItemHost(Of TItemType As {BaseItem}) 
    Property Items As BindingList(Of TItemType) '-- No Out parameter allowed :(
End Interface 

Public Class BaseGroup(Of TGroup AS {BaseItem}) 
    Inherits BaseItem 
    Implements IItemHost(Of TGroup) 

    '-- This is the key property, all BaseGroup implimentors need an Items property of their specific type 
    Public Property Items As New BindingList(Of TGroup)() Implements IItemHost(Of TGroup).Items 

End Class 

Public Class SpecialItem 
    Inherits BaseGroup(Of ExtraSpecialItem) 

End Class 

Public Class ExtraSpecialItem 
    Inherits BaseGroup(Of LeafItem) 

End Class 

Public Class LeafItem 
    Inherits BaseItem 

End Class 

По большей части это все на самом деле работает. То, что я не могу сделать, это:

Dim root = New SpecialItem() 
root.ItemNameOrSomething = "Testing 1" 
root.Items.Add(New ExtraSpecialItem() With {.ItemNameOrSomething = "Testing 2"}) 

'-- This specifically, no casting options available. 
Dim item = CType(root, IItemHost(Of BaseItem)) 
Dim subItems = item.Items 
Dim testing2Text = subItems.First().ItemNameOrSomething '-- = "Testing 2" 
+0

Держись ... Я мог бы решить ее ... – Tom

+0

Нет, я был неправ, я подумал, что, указав на BaseItem IItemHost он будет работать, но это означает, что я должен был бы привести экземпляр SpecialItem to CType (si, IItemHost (из ExtraSpecialItem)). Элементы (для доступа к объектам на этом объекте). – Tom

ответ

0

Хорошо это точно не решить эту проблему, но это решение я готов рассчитаться с сейчас.

Если я изменил свой BaseItem на коллекцию «BaseItems», мои унаследованные классы BaseGroup могут иметь элементы IEnumerable по умолчанию. Если мне нужно будет вернуться к этой коллекции, я могу просто использовать BaseItems. Для стандартного цикла через элементы я могу использовать Элементы, и это даст мне правильное кастинг.

Public MustInherit Class BaseItem 

    Public Property ItemNameOrSomething As String 
    Public Property BaseItems As New BindingList(Of BaseItem)() 

End Class 

Public Class BaseGroup(Of TGroup As {BaseItem}) 
    Inherits BaseItem 

    Public ReadOnly Property Items As IEnumerable(Of TGroup) 
     Get 
      Return BaseItems.Cast(Of TGroup)() 
     End Get 
    End Property 

End Class 
+0

В качестве дополнительного побочного элемента, если вы используете что-то вроде Infragistics Grids для привязки свойства Items (особенно, если оно сильно иерархическое, что явно), используйте BindingList (Of TGroup), а не IEnumerable. Я использую кешированный BindingList, который обновляется при запуске BaseItems.ListChanged. – Tom

Смежные вопросы