Почему я не могу получить доступ к свойствам Internal/Friend из динамического объекта?
Сначала я собираюсь показать код VB.NET, потому что поведение его эквивалента в C# более запутанное (см. Ниже).
Рассмотрим следующие три класса:
Public Class BaseClass
Private Shared Rand As New Random
Public Shared Function CreateDerived() As BaseClass
Return If(Rand.Next(1, 3) = 1, New DerivedClass1(), New DerivedClass2())
End Function
End Class
Public Class DerivedClass1
Inherits BaseClass
Sub New()
MyProperty = 1
End Sub
Friend Property MyProperty As Integer
End Class
Public Class DerivedClass2
Inherits BaseClass
Sub New()
MyProperty = 2
End Sub
Friend Property MyProperty As Integer
End Class
Теперь, когда я пытаюсь сделать что-то вроде этого:
Sub Foo()
Dim targetClass As BaseClass = BaseClass.CreateDerived()
Dim Casted
If TypeOf (targetClass) Is DerivedClass1 Then
Casted = DirectCast(targetClass, DerivedClass1)
ElseIf TypeOf (targetClass) Is DerivedClass2 Then
Casted = DirectCast(targetClass, DerivedClass2)
Else
Exit Sub
End If
Console.WriteLine(Casted.MyProperty) 'Throws an exception.
End Sub
Кажется, я не могу получить доступ MyProperty
и я получаю следующее исключение:
Открытый член 'MyProperty' для типа 'DerivedClass1' не найден.
Итак, когда я изменяю уровень доступа MyProperty
в Public
код работает как положено.
Странная часть, когда я пытаюсь использовать C# эквивалент вышеупомянутого кода на VS 2015, он работает просто отлично, но на.NET Fiddler это не так.
Вот пример C# для.NET Fiddler, где я получаю то же поведение, что и VB.NET.
Итак, я что-то не так делаю?
1 ответ
Я не могу ответить на ПОЧЕМУ этого вопроса, но я могу предоставить обходной путь.
Создать Interface
и реализовать его в своем BaseClass
, Тогда вместо того, чтобы объявить Casted
как Object
Вы можете объявить его как интерфейс, который будет правильно выставлять желаемое свойство с тем же модификатором доступа, что и раньше.
Полный пример ниже.
Sub Foo()
Dim targetClass As BaseClass = BaseClass.CreateDerived()
Dim Casted As Interf
If TypeOf (targetClass) Is DerivedClass1 Then
Casted = DirectCast(targetClass, DerivedClass1)
ElseIf TypeOf (targetClass) Is DerivedClass2 Then
Casted = DirectCast(targetClass, DerivedClass2)
Else
Exit Sub
End If
Console.WriteLine(Casted.MyProperty) 'Throws an exception.
End Sub
Friend Interface Interf
Property MyProperty As Integer
End Interface
Public Class BaseClass
Implements Interf
Private Shared Rand As New Random
Friend Overridable Property MyProperty As Integer Implements Interf.MyProperty
Public Shared Function CreateDerived() As BaseClass
Return If(Rand.Next(1, 3) = 1, New DerivedClass1(), New DerivedClass2())
End Function
End Class
Public Class DerivedClass1
Inherits BaseClass
Sub New()
MyProperty = 1
End Sub
Friend Overrides Property MyProperty As Integer
End Class
Public Class DerivedClass2
Inherits BaseClass
Sub New()
MyProperty = 2
End Sub
Friend Overrides Property MyProperty As Integer
End Class