VB .Net - ShouldSerialize 函数
VB .Net - ShouldSerialize function
我对 ShouldSerialize 函数有疑问。
我定义了一个带有标签(名为 Label1)的用户控件。
现在我将下面的代码放在用户控件中 class :
Imports System.ComponentModel
Public Class UserControl1
Dim _Range As UShort = 100
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Text = _Range
End Sub
Public Function ShouldSerializeTBValueRange() As Boolean
Return _Range <> 200
End Function
Public Sub ResetTBValueRange()
_Range = 200
Label1.Text = _Range
End Sub
Public Property TBValueRange As UShort
Get
Return _Range
End Get
Set(ByVal Steps As UShort)
_Range = Steps
Label1.Text = _Range
End Set
End Property
End Class
现在在新表单中包含用户控件。
在用户控件的属性网格中,您可以找到 属性 TBValueRange。
如果您右键单击 属性 名称,您可以重新初始化 属性.
重新初始化后,您可以在 属性.
中看到值 200
现在,重新生成项目会将 属性 重置为初始值 (id 100)。
为什么值 200 没有保留?
如果我将函数 ShouldSerializeTBValueRange() 中的行 Return _Range <> 200
替换为
Return Not _Range.Equals(200)
它会起作用的。
我不明白。
谁能解释一下?
这些方法按编码工作。 似乎 无法按预期工作的是 Not _Range.Equals(200)
部分。
你将_Range
初始化为100:Dim _Range As UShort = 100
然后,你的ShouldSerializeTBValueRange
方法告诉VS 只在不是[=89=时保存范围值] 200
: Return _Range <> 200
所以,当你在IDE中重置为200
时,它不会保存200
的值,而初始值[=24] =] 显示。
代码使用一个值作为默认值,100
但对 ShouldSerialize
测试使用不同的值。您应该将其更改为使用默认值 200:
Dim _Range As UShort = 200
或 将 ShouldSerialize
测试更改为使用 100
:
Public Function ShouldSerializeTBValueRange() As Boolean
Return _Range <> 100
End Function
将默认值视为默认值,并且仅使用 一个 值作为默认值一切正常,仅使用 ShouldSerializexxx
和 Resetxxx
没有需要其他任何东西。
' THIS is the default value -
' ie the value that need not be saved because the
' control automatically starts with that value
Dim _Range As UShort = 200US
' Controls:
' - displays the prop value in Bold in the property window
' when the value is NOT the default
' - saves the value when it is NOT the default
' - enables/disables the RESET function
Public Function ShouldSerializeTBValueRange() As Boolean
Return (_Range <> 200US)
End Function
使用一个值作为实际默认值 (100),然后根据 不同的 值 (200) 返回 T/F 结果
- 100 在不需要时被保存
- 200 没有 应该被保存
Reset
菜单项和 粗体值 处于错误状态
奇怪的是 Not _Range.Equals(200)
似乎失败了。它 returns False
在重置(到 200)后导致值在实际上不应该被保存时被保存。为此有 2 个重载:
UInt16.Equals(obj As Object) As Boolean
UInt16.Equals(v As UShort) As Boolean
如果您传递的不是实际的 UInt16/UShort
,该值将被装箱为 Object
。所以,Not _Range.Equals(200)
使用第一个,因为 200
是 Int32
。该版本的 ILCode 是:
public override bool Equals(object obj)
{
return obj is ushort && this == (ushort)obj;
}
测试将无法通过第一个测试,因为 obj
包含一个 Int32
。如果你传递一个 UShort
,它将起作用:
UShort.Equals(_Range, 200US)
'or:
_Range.Equals(200US)
了解不同数据类型的所有充分理由,避免装箱 (As Object
) 并永远设置 Option Strict On
。
感谢大家花时间回答我的问题。
我找到了答案:当 ShouldSerialize 函数 return 为 false 时,属性 值未保存在文件 Form1.designer.vb 中,因此它获得原始值。
对于我需要的 ShouldSerialize 函数应该总是 return true.
Public Function ShouldSerializeTBValueRange() As Boolean
Return true
End Function
因此 属性 值将始终保存。
现在,我正在寻找的是如何控制 属性 网格的上下文菜单。
我希望选项 "Reinit" 在值好的时候变灰。
终于,我找到了一些东西,使用 PropertyDescriptor。
有兴趣的可以把属性保存在designer.vb文件里,测试一下要重置的值。
这是我的程序,基于 MSDN - Microsft:
的文章
Imports System.ComponentModel
Imports System.Windows.Forms.Design
<Designer(GetType(DemoControlDesigner))>
Public Class UserControl1
Dim _MyProperty1 As String = "Test1"
Dim _MyProperty2 As Integer = 100
Dim _MyProperty3 As UShort = 200
Public Sub New()
InitializeComponent()
End Sub
Public Function CanResetMyProperty1() As Boolean
Return _MyProperty1 <> "Test"
End Function
Public Sub ResetMyProperty1()
_MyProperty1 = "Test"
End Sub
Public Property MyProperty1 As String
Get
Return _MyProperty1
End Get
Set(ByVal Value As String)
_MyProperty1 = Value
End Set
End Property
Public Function CanResetMyProperty2() As Boolean
Return _MyProperty2 <> 150
End Function
Public Sub ResetMyProperty2()
_MyProperty2 = 150
End Sub
Public Property MyProperty2 As Integer
Get
Return _MyProperty2
End Get
Set(ByVal Value As Integer)
_MyProperty2 = Value
End Set
End Property
Public Function CanResetMyProperty3() As Boolean
Return _MyProperty3 <> _MyProperty2
End Function
Public Sub ResetMyProperty3()
_MyProperty3 = _MyProperty2
End Sub
Public Property MyProperty3 As UShort
Get
Return _MyProperty3
End Get
Set(ByVal Value As UShort)
_MyProperty3 = Value
End Set
End Property
End Class
Friend NotInheritable Class SerializePropertyDescriptor
Inherits PropertyDescriptor
Private _pd As PropertyDescriptor = Nothing
Public Sub New(ByVal pd As PropertyDescriptor)
MyBase.New(pd)
_pd = pd
End Sub
Public Overrides ReadOnly Property Attributes() As AttributeCollection
Get
Return Me._pd.Attributes
End Get
End Property
Protected Overrides Sub FillAttributes(ByVal attributeList As IList)
MyBase.FillAttributes(attributeList)
End Sub
Public Overrides ReadOnly Property ComponentType() As Type
Get
Return Me._pd.ComponentType
End Get
End Property
Public Overrides ReadOnly Property Converter() As TypeConverter
Get
Return Me._pd.Converter
End Get
End Property
Public Overrides Function GetEditor(ByVal editorBaseType As Type) As Object
Return Me._pd.GetEditor(editorBaseType)
End Function
Public Overrides ReadOnly Property IsReadOnly() As Boolean
Get
Return Me._pd.IsReadOnly
End Get
End Property
Public Overrides ReadOnly Property PropertyType() As Type
Get
Return Me._pd.PropertyType
End Get
End Property
Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
Try
Return CallByName(component, "CanReset" & _pd.Name, CallType.Get, Nothing)
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return False
End Function
Public Overrides Function GetValue(ByVal component As Object) As Object
Return Me._pd.GetValue(component)
End Function
Public Overrides Sub ResetValue(ByVal component As Object)
Me._pd.ResetValue(component)
End Sub
Public Overrides Sub SetValue(ByVal component As Object, ByVal val As Object)
Me._pd.SetValue(component, val)
End Sub
Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
Return True
End Function
End Class
Class DemoControlDesigner
Inherits ControlDesigner
Dim PropertiesToSerialize As String() = {"MyProperty1", "MyProperty2", "MyProperty3"}
Protected Overrides Sub PostFilterProperties(ByVal properties As IDictionary)
Dim original As PropertyDescriptor
For Each PropName As String In PropertiesToSerialize
If properties.Contains(PropName) Then
original = properties(PropName)
properties(PropName) = New SerializePropertyDescriptor(original)
End If
Next
MyBase.PostFilterProperties(properties)
End Sub
End Class
对于每个应该序列化并测试重置的 属性,我们应该编写一个子 "CanResetPropertyName" 来测试要重置的值(参见示例)。
即使我们重新生成项目,这些值现在仍然存在。
它对我来说很好用,也许可以改进。
此致。
我对 ShouldSerialize 函数有疑问。
我定义了一个带有标签(名为 Label1)的用户控件。
现在我将下面的代码放在用户控件中 class :
Imports System.ComponentModel
Public Class UserControl1
Dim _Range As UShort = 100
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Text = _Range
End Sub
Public Function ShouldSerializeTBValueRange() As Boolean
Return _Range <> 200
End Function
Public Sub ResetTBValueRange()
_Range = 200
Label1.Text = _Range
End Sub
Public Property TBValueRange As UShort
Get
Return _Range
End Get
Set(ByVal Steps As UShort)
_Range = Steps
Label1.Text = _Range
End Set
End Property
End Class
现在在新表单中包含用户控件。
在用户控件的属性网格中,您可以找到 属性 TBValueRange。
如果您右键单击 属性 名称,您可以重新初始化 属性.
重新初始化后,您可以在 属性.
中看到值 200
现在,重新生成项目会将 属性 重置为初始值 (id 100)。
为什么值 200 没有保留?
如果我将函数 ShouldSerializeTBValueRange() 中的行 Return _Range <> 200
替换为
Return Not _Range.Equals(200)
它会起作用的。 我不明白。
谁能解释一下?
这些方法按编码工作。 似乎 无法按预期工作的是 Not _Range.Equals(200)
部分。
你将
_Range
初始化为100:Dim _Range As UShort = 100
然后,你的
ShouldSerializeTBValueRange
方法告诉VS 只在不是[=89=时保存范围值]200
:Return _Range <> 200
所以,当你在IDE中重置为
200
时,它不会保存200
的值,而初始值[=24] =] 显示。
代码使用一个值作为默认值,100
但对 ShouldSerialize
测试使用不同的值。您应该将其更改为使用默认值 200:
Dim _Range As UShort = 200
或 将 ShouldSerialize
测试更改为使用 100
:
Public Function ShouldSerializeTBValueRange() As Boolean
Return _Range <> 100
End Function
将默认值视为默认值,并且仅使用 一个 值作为默认值一切正常,仅使用 ShouldSerializexxx
和 Resetxxx
没有需要其他任何东西。
' THIS is the default value -
' ie the value that need not be saved because the
' control automatically starts with that value
Dim _Range As UShort = 200US
' Controls:
' - displays the prop value in Bold in the property window
' when the value is NOT the default
' - saves the value when it is NOT the default
' - enables/disables the RESET function
Public Function ShouldSerializeTBValueRange() As Boolean
Return (_Range <> 200US)
End Function
使用一个值作为实际默认值 (100),然后根据 不同的 值 (200) 返回 T/F 结果
- 100 在不需要时被保存
- 200 没有 应该被保存
Reset
菜单项和 粗体值 处于错误状态
奇怪的是 Not _Range.Equals(200)
似乎失败了。它 returns False
在重置(到 200)后导致值在实际上不应该被保存时被保存。为此有 2 个重载:
UInt16.Equals(obj As Object) As Boolean
UInt16.Equals(v As UShort) As Boolean
如果您传递的不是实际的 UInt16/UShort
,该值将被装箱为 Object
。所以,Not _Range.Equals(200)
使用第一个,因为 200
是 Int32
。该版本的 ILCode 是:
public override bool Equals(object obj)
{
return obj is ushort && this == (ushort)obj;
}
测试将无法通过第一个测试,因为 obj
包含一个 Int32
。如果你传递一个 UShort
,它将起作用:
UShort.Equals(_Range, 200US)
'or:
_Range.Equals(200US)
了解不同数据类型的所有充分理由,避免装箱 (As Object
) 并永远设置 Option Strict On
。
感谢大家花时间回答我的问题。
我找到了答案:当 ShouldSerialize 函数 return 为 false 时,属性 值未保存在文件 Form1.designer.vb 中,因此它获得原始值。
对于我需要的 ShouldSerialize 函数应该总是 return true.
Public Function ShouldSerializeTBValueRange() As Boolean
Return true
End Function
因此 属性 值将始终保存。
现在,我正在寻找的是如何控制 属性 网格的上下文菜单。
我希望选项 "Reinit" 在值好的时候变灰。
终于,我找到了一些东西,使用 PropertyDescriptor。
有兴趣的可以把属性保存在designer.vb文件里,测试一下要重置的值。
这是我的程序,基于 MSDN - Microsft:
Imports System.ComponentModel
Imports System.Windows.Forms.Design
<Designer(GetType(DemoControlDesigner))>
Public Class UserControl1
Dim _MyProperty1 As String = "Test1"
Dim _MyProperty2 As Integer = 100
Dim _MyProperty3 As UShort = 200
Public Sub New()
InitializeComponent()
End Sub
Public Function CanResetMyProperty1() As Boolean
Return _MyProperty1 <> "Test"
End Function
Public Sub ResetMyProperty1()
_MyProperty1 = "Test"
End Sub
Public Property MyProperty1 As String
Get
Return _MyProperty1
End Get
Set(ByVal Value As String)
_MyProperty1 = Value
End Set
End Property
Public Function CanResetMyProperty2() As Boolean
Return _MyProperty2 <> 150
End Function
Public Sub ResetMyProperty2()
_MyProperty2 = 150
End Sub
Public Property MyProperty2 As Integer
Get
Return _MyProperty2
End Get
Set(ByVal Value As Integer)
_MyProperty2 = Value
End Set
End Property
Public Function CanResetMyProperty3() As Boolean
Return _MyProperty3 <> _MyProperty2
End Function
Public Sub ResetMyProperty3()
_MyProperty3 = _MyProperty2
End Sub
Public Property MyProperty3 As UShort
Get
Return _MyProperty3
End Get
Set(ByVal Value As UShort)
_MyProperty3 = Value
End Set
End Property
End Class
Friend NotInheritable Class SerializePropertyDescriptor
Inherits PropertyDescriptor
Private _pd As PropertyDescriptor = Nothing
Public Sub New(ByVal pd As PropertyDescriptor)
MyBase.New(pd)
_pd = pd
End Sub
Public Overrides ReadOnly Property Attributes() As AttributeCollection
Get
Return Me._pd.Attributes
End Get
End Property
Protected Overrides Sub FillAttributes(ByVal attributeList As IList)
MyBase.FillAttributes(attributeList)
End Sub
Public Overrides ReadOnly Property ComponentType() As Type
Get
Return Me._pd.ComponentType
End Get
End Property
Public Overrides ReadOnly Property Converter() As TypeConverter
Get
Return Me._pd.Converter
End Get
End Property
Public Overrides Function GetEditor(ByVal editorBaseType As Type) As Object
Return Me._pd.GetEditor(editorBaseType)
End Function
Public Overrides ReadOnly Property IsReadOnly() As Boolean
Get
Return Me._pd.IsReadOnly
End Get
End Property
Public Overrides ReadOnly Property PropertyType() As Type
Get
Return Me._pd.PropertyType
End Get
End Property
Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
Try
Return CallByName(component, "CanReset" & _pd.Name, CallType.Get, Nothing)
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return False
End Function
Public Overrides Function GetValue(ByVal component As Object) As Object
Return Me._pd.GetValue(component)
End Function
Public Overrides Sub ResetValue(ByVal component As Object)
Me._pd.ResetValue(component)
End Sub
Public Overrides Sub SetValue(ByVal component As Object, ByVal val As Object)
Me._pd.SetValue(component, val)
End Sub
Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
Return True
End Function
End Class
Class DemoControlDesigner
Inherits ControlDesigner
Dim PropertiesToSerialize As String() = {"MyProperty1", "MyProperty2", "MyProperty3"}
Protected Overrides Sub PostFilterProperties(ByVal properties As IDictionary)
Dim original As PropertyDescriptor
For Each PropName As String In PropertiesToSerialize
If properties.Contains(PropName) Then
original = properties(PropName)
properties(PropName) = New SerializePropertyDescriptor(original)
End If
Next
MyBase.PostFilterProperties(properties)
End Sub
End Class
对于每个应该序列化并测试重置的 属性,我们应该编写一个子 "CanResetPropertyName" 来测试要重置的值(参见示例)。
即使我们重新生成项目,这些值现在仍然存在。
它对我来说很好用,也许可以改进。
此致。