我有一个应用程序,我希望能够在运行时编辑任何类型(字体,颜色,点等)并使用任何.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)
如果我将对象传递给属性网格,它可以工作但如果我传递包装器的实例则不起作用。
我已经通过使用reflection.Emit来解决问题,即可动态创建所需类型的非通用包装,但我怀疑这是过度杀戮。
有什么想法吗?
ETA:
如果我使用网格编辑属性,比如一个尚未定义的字体,我有什么问题。
如果我定义:
Dim f as Font = Nothing
,并将其传递给包装器,属性网格按预期显示(无)和带有...的按钮以选择字体。
我的问题是如何在运行时执行相当于Dim myObject As'Type'= Nothing。
我找不到办法做到这一点,但幸运的是包装和我的类型,这不是一个问题。 我将Pradeep的代码(看看答案)改为:
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
问题解决了!
答案 0 :(得分:3)
我认为这应该有效。我在C#中测试了它,并使用转换器在VB.net中获取代码
这是C#中的代码
Type generic = typeof(Wrapper<>);
Type specific = generic.MakeGenericType(o.GetType());
ConstructorInfo ci = specific.GetConstructor(new Type[] { o.GetType() });
object o1 = ci.Invoke(new object[] { o });
propertyGrid1.SelectedObject = o1;
VB.NET
Dim generic As Type = Type.GetType(Wrapper<>)
Dim specific As Type = generic.MakeGenericType(o.GetType())
Dim ci As ConstructorInfo = specific.GetConstructor(New Type() {o.GetType() })
Dim o1 As Object = ci.Invoke(New Object(){ o })
propertyGrid1.SelectedObject = o1