У меня есть приложение, в котором я хотел бы иметь возможность редактировать любой тип (шрифт, цвет, точка и т. Д.) Во время выполнения и использовать любой из стандартных редакторов типов .Net. (например, средство выбора шрифта / цвета).
Вместо того, чтобы заново изобретать колесо, я решил использовать элемент управления сеткой свойств.
Если я передаю объект, скажем, шрифт, в сетку, он перечисляет все поля отдельно, без возможности открыть средство выбора шрифта.
Поэтому я создал этот универсальный класс-оболочку:
Private Class Wrapper(Of T)
Private _Value As T
Public Property Value() As T
Get
Return Me._Value
End Get
Set(ByVal value As T)
Me._Value = value
End Set
End Property
Public Sub New(ByVal Value As T)
Me._Value = Value
End Sub
End Class
Вместо передачи объекта шрифта в сетку, я передаю экземпляр оболочки. Сетка свойств ведет себя так, как мне хотелось бы.
Это работает, но проблема в том, что объект может быть любого типа, и я не могу написать что-то вроде -
Dim MyWrapper = New Wrapper(of T)(myObject).
По сути, у меня есть информация, содержащая полное имя типа сборки и строковое представление объекта. Затем я использую конвертер типов для создания объекта:
Dim ID As String = "System.Drawing.Font, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
Dim PropertyValue As String = "Arial, 12px, style=Bold, Strikeout"
Dim T As Type = System.Type.GetType(ID)
Dim tc As TypeConverter = TypeDescriptor.GetConverter(T)
Dim o As Object = tc.ConvertFromString(PropertyValue)
Если я передаю объект в сетку свойств, он работает, но не работает, если я передаю экземпляр оболочки.
Я решил проблему с помощью отражения. Emit для создания не универсальной оболочки необходимого типа на лету, но я подозреваю, что это слишком.
Есть идеи?
ETA:
У меня была проблема с тем, что делать, если я использовал Grid для редактирования свойства, скажем шрифта, которое еще не было определено.
Если я определю:
Dim f as Font = Nothing
и передайте это оболочке, сетка свойств будет отображаться, как и ожидалось, с (нет) и кнопкой с ..., чтобы выбрать шрифт.
Моя проблема заключалась в том, как сделать эквивалент Dim myObject As 'Type' = Nothing во время выполнения.
Я не мог найти способ сделать это, но к счастью с оберткой и моим типом, это не было проблемой.
Я изменил код Прадипа (посмотрите на ответы) на:
Dim genericType As Type = GetType(Wrapper(Of ))
Dim specificType As Type = genericType.MakeGenericType(T)
Dim ci As ConstructorInfo = specificType.GetConstructor(New Type() {T})
Dim wrappedObject As Object = ci.Invoke(New Object() {Nothing})
Me.PropertyGrid1.SelectedObject = wrappedObject
Проблема решена!