Пол, вы не спрашивали: «Могу ли я это сделать»? Я предполагаю, что вы хотите знать , как сделать это!
Мы должны были сделать это в проекте - есть много классов, которые мы настраиваем в общем виде только один раз, затем инициализируем свойства, специфичные для производных классов. Я использую VB, так что мой образец в VB (жесткий noogies), но я украл образец VB с этого сайта, который также имеет лучшую версию C #:
http://www.eggheadcafe.com/tutorials/aspnet/a4264125-fcb0-4757-9d78-ff541dfbcb56/net-reflection--copy-cl.aspx
Пример кода:
Imports System
Imports System.Collections.Generic
Imports System.Reflection
Imports System.Text
Imports System.Diagnostics
Module ClassUtils
Public Sub CopyProperties(ByVal dst As Object, ByVal src As Object)
Dim srcProperties() As PropertyInfo = src.GetType.GetProperties
Dim dstType = dst.GetType
If srcProperties Is Nothing Or dstType.GetProperties Is Nothing Then
Return
End If
For Each srcProperty As PropertyInfo In srcProperties
Dim dstProperty As PropertyInfo = dstType.GetProperty(srcProperty.Name)
If dstProperty IsNot Nothing Then
If dstProperty.PropertyType.IsAssignableFrom(srcProperty.PropertyType) = True Then
dstProperty.SetValue(dst, srcProperty.GetValue(src, Nothing), Nothing)
End If
End If
Next
End Sub
End Module
Module Module1
Class base_class
Dim _bval As Integer
Public Property bval() As Integer
Get
Return _bval
End Get
Set(ByVal value As Integer)
_bval = value
End Set
End Property
End Class
Class derived_class
Inherits base_class
Public _dval As Integer
Public Property dval() As Integer
Get
Return _dval
End Get
Set(ByVal value As Integer)
_dval = value
End Set
End Property
End Class
Sub Main()
' NARROWING CONVERSION TEST
Dim b As New base_class
b.bval = 10
Dim d As derived_class
'd = CType(b, derived_class) ' invalidcast exception
'd = DirectCast(b, derived_class) ' invalidcast exception
'd = TryCast(b, derived_class) ' returns 'nothing' for c
d = New derived_class
CopyProperties(d, b)
d.dval = 20
Console.WriteLine(b.bval)
Console.WriteLine(d.bval)
Console.WriteLine(d.dval)
Console.ReadLine()
End Sub
End Module
Конечно, на самом деле это не кастинг. Это создает новый производный объект и копирует свойства из родительского, оставляя дочерние свойства пустыми. Это все, что мне нужно было сделать, и, похоже, это все, что тебе нужно сделать. Обратите внимание, что он копирует только свойства, а не члены (открытые переменные) в классе (но вы можете расширить его, чтобы сделать это, если вам стыдно выставлять открытых членов).
При приведении в общем случае создаются 2 переменные, указывающие на один и тот же объект (мини-учебник здесь, пожалуйста, не бросайте в меня исключения из угловых регистров) Это имеет серьезные последствия (упражнение для читателя)!
Конечно, я должен сказать, почему язык не отпускает вас с базы для получения экземпляра, а делает это другим путем. представьте себе случай, когда вы можете взять экземпляр текстового поля winforms (производного) и сохранить его в переменной типа Winforms control. Конечно, «control» может перемещать объект вокруг OK, и вы можете иметь дело со всеми «controll-y» вещами в текстовом поле (например, свойства top, left, .text). Специфичные для текстового поля вещи (например, .multiline) не могут быть видны без приведения переменной типа 'control', указывающей на текстовое поле в памяти, но он все еще там в памяти.
Теперь представьте, что у вас есть элемент управления, и вы хотите поместить в него переменную типа textbox. В элементе управления в памяти отсутствуют «многострочные» и другие текстовые элементы. Если вы попытаетесь сослаться на них, элемент управления не будет магически увеличивать многострочное свойство! Свойство (смотрите здесь как переменную-член, которая на самом деле хранит значение - потому что оно включено в памяти экземпляра текстового поля) должен существовать. Поскольку вы применяете каст, помните, это должен быть тот же объект, на который вы указываете. Следовательно, это не является языковым ограничением, философски невозможно описать таким образом.