Я надеюсь, что не повторяю вопрос, который уже решен, но у меня были проблемы, чтобы найти решение для моей проблемы в подобных вопросах. Я нашел эту топи c на форуме: Приведение объекта к двум интерфейсам одновременно, чтобы вызвать обобщенный c метод . Честно говоря, мой C# очень плох, так как я кодирую только на VB. NET, и я думаю, что моя проблема немного другая (унаследованные интерфейсы вместо автономных).
Моя проблема также связана с Сериализация (XML), для которой моя реализация обобщений не дает исключение. Дело в том, что я должен привести мой обобщенный тип c, который сериализатор должен десериализовать, к интерфейсу, что приведет к исключению. Чтобы лучше объяснить, см. Упрощенный пример кода ниже:
Public Interface IParent
Property ParentProp As String
End Interface
Public Interface IChild
Inherits IParent
Property ChildProp As String
End Interface
Public Class ExampleClass
Implements IChild
Public Property ChildProp As String = "Child Property" Implements IChild.ChildProp
Public Property ParentProp As String = "Parent Property" Implements IParent.ParentProp
End Class
Public Class ExampleListClass
Inherits List(Of Integer)
Implements IChild
Public Property ChildProp As String = "List Child Property" Implements IChild.ChildProp
Public Property ParentProp As String = "List Parent Property" Implements IParent.ParentProp
End Class
Public Class TestEnv
Public Shared Sub Main()
Dim str As String
Dim locExampleListClass = New ExampleListClass
str = TestEnv.Method1(Of Integer, ExampleListClass)(locExampleListClass)
MessageBox.Show(str, "locExampleListClass", MessageBoxButtons.OK, MessageBoxIcon.Information)
Dim locExampleClass = New ExampleClass
str = TestEnv.Method2(locExampleClass)
str = TestEnv.Method2_Dirty(locExampleClass)
MessageBox.Show(str, "locExampleClass", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Public Shared Function Method1(Of T, C As {IList(Of T), IParent})(ByRef Instance As C) As String
If TypeOf (Instance) Is IChild Then
'Since instance is of type C which is restricted to IParent, the passed instance is a list which implements IChild (and of course IParent - because IChild inherits IParent)
Dim CastedInstance = DirectCast(Instance, IChild)
'!-----------------PseudoCode-----------------!
'Dim CastedInstance = DirectCast(Instance, {C, IChild})
Dim ReturnVal = TestEnv.Method2(CastedInstance)
Dim fake = TestEnv.Method2_Dirty(Instance)
Return ReturnVal
Else
'Something else is done (e.g. deactivating context menues only useful for IChild)
Return Instance.ParentProp
End If
'------------------------------------------------------------------------------------------
End Function
Public Shared Function Method2(Of T As {IChild})(ByRef Instance As T) As String
Return Instance.ChildProp
'Note: Xml-serialization into T when T is an interface seems not possible. Thus type C in Method1 needs to be maintained but extended to IChild
End Function
Public Shared Function Method2_Dirty(Of T As {IParent})(ByRef Instance As T) As String
'This would work but is not very nice (there is a reason why T shall be restricted to IChild in the first place - no ifs or trycasts needed)
If TypeOf (Instance) Is IChild Then
Return DirectCast(Instance, IChild).ChildProp
Else
Throw New Exception("The input parameter needs to be of type IChild but I am too stupid to make it work")
End If
End Function
End Class
Итак, есть два примера классов, один из которых является списком и очень прост. Оба реализуют интерфейс IChild. Метод 1, однако, ограничивает входной аргумент только IParent и проверяет, реализован ли IChild. Если не что-то еще сделано. Если да, то экземпляр может быть брошен без проблем. Таким образом, на данный момент я знаю, что экземпляр реализует IList (из T) и IChild. Теперь Method2 может быть вызван с приведенным экземпляром. Все это, очевидно, компилируется и работает. Моя проблема в том, что Method2 в моем случае является десериализатором (пытается указать это, передав Instance ByRef). Поскольку CastedInstance имеет тип IChild, десериализатор выдает исключение.
Таким образом, мне по-прежнему нужен тип C, но расширенный IChild. После оператора if в Method1 я знаю, что экземпляр полностью выполняет ограничения, но мне не удается реализовать правильный код (см. Комментарий PseudeCode). Я думаю, я мог бы реализовать Method2_Dirty, который ограничивает только IParent и делать проверки типов и trycasts. Тем не менее, это кажется не очень хорошим, поскольку с тех пор исключения генерируются во время выполнения, а не во время кодирования перед компиляцией.
Как уже было сказано в начале, я надеюсь, что не буду повторять какие-либо вопросы и жду ваших отзывов. Спасибо