类型转换器示例
更新:2007 年 11 月
此示例演示如何创建一个名为 AuthorConverter 的类型转换器,该类型转换器将与来自其他控件创作示例的 Author 对象一起使用。ASP.NET 在运行时使用类型转换器来对控件状态和视图状态中存储的对象进行序列化和反序列化。AuthorConverter 示例将一个 Author 对象转换为 String,并将一个 String 表示形式转换为 Author 对象。服务器控件属性示例中对 Author 类型进行了描述。
使用 TypeConverterAttribute 可使类型转换器与类型(或为其定义转换器的类型的属性)关联。AuthorConverter 允许 Book 控件在视图状态中存储 Author 属性。仅当自定义类型已经定义了类型转换器并与类型关联时,才可以将该自定义类型存储在视图状态中。
AuthorConverter 类派生自 ExpandableObjectConverter,因此可视化设计器中的属性浏览器可以提供用于编辑 Author 类型的子属性的展开/折叠用户界面。
AuthorConverter 类的代码清单
' AuthorConverter.vb
Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization
Imports System.Globalization
Imports System.Reflection
Namespace Samples.AspNet.VB.Controls
Public Class AuthorConverter
Inherits ExpandableObjectConverter
Public Overrides Function CanConvertFrom( _
ByVal context As ITypeDescriptorContext, _
ByVal sourceType As Type) As Boolean
If sourceType Is GetType(String) Then
Return True
End If
Return MyBase.CanConvertFrom(context, sourceType)
End Function
Public Overrides Function CanConvertTo( _
ByVal context As ITypeDescriptorContext, _
ByVal destinationType As Type) As Boolean
If destinationType Is GetType(String) Then
Return True
End If
Return MyBase.CanConvertTo(context, destinationType)
End Function
Public Overrides Function ConvertFrom( _
ByVal context As ITypeDescriptorContext, _
ByVal culture As CultureInfo, ByVal value As Object) As Object
If value Is Nothing Then
Return New Author()
End If
If (TypeOf value Is String) Then
Dim s As String = CStr(value)
If s.Length = 0 Then
Return New Author()
End If
Dim parts() As String = s.Split(" ".ToCharArray)
' Determine if name is stored as first and last,
' first, middle, and last,
' or is in error.
If (parts.Length < 2) Or (parts.Length > 3) Then
Throw New ArgumentException( _
"Name must have 2 or 3 parts.", "value")
End If
If parts.Length = 2 Then
Return New Author(parts(0), parts(1))
End If
If parts.Length = 3 Then
Return New Author(parts(0), parts(1), parts(2))
End If
End If
Return MyBase.ConvertFrom(context, culture, value)
End Function
Public Overrides Function ConvertTo( _
ByVal context As ITypeDescriptorContext, _
ByVal culture As CultureInfo, ByVal value As Object, _
ByVal destinationType As Type) As Object
If value IsNot Nothing Then
If Not (TypeOf value Is Author) Then
Throw New ArgumentException("Invalid Author", _
"value")
End If
End If
If destinationType Is GetType(String) Then
If value Is Nothing Then
Return String.Empty
End If
Dim auth As Author = CType(value, Author)
If auth.MiddleName <> String.Empty Then
Return String.Format("{0} {1} {2}", _
auth.FirstName, _
auth.MiddleName, _
auth.LastName)
Else
Return String.Format("{0} {1}", _
auth.FirstName, _
auth.LastName)
End If
End If
Return MyBase.ConvertTo(context, culture, value, _
destinationType)
End Function
End Class
End Namespace
// AuthorConverter.cs
using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;
namespace Samples.AspNet.CS.Controls
{
public class AuthorConverter : ExpandableObjectConverter
{
public override bool CanConvertFrom(
ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(
ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext
context, CultureInfo culture, object value)
{
if (value == null)
{
return new Author();
}
if (value is string)
{
string s = (string)value;
if (s.Length == 0)
{
return new Author();
}
string[] parts = s.Split(' ');
// Determine if name is stored as first and
// last; first, middle, and last;
// or is in error.
if ((parts.Length < 2) || (parts.Length > 3))
{
throw new ArgumentException(
"Name must have 2 or 3 parts.", "value");
}
if (parts.Length == 2)
{
return new Author(parts[0], parts[1]);
}
if (parts.Length == 3)
{
return new Author(parts[0], parts[1], parts[2]);
}
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(
ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
if (value != null)
{
if (!(value is Author))
{
throw new ArgumentException(
"Invalid Author", "value");
}
}
if (destinationType == typeof(string))
{
if (value == null)
{
return String.Empty;
}
Author auth = (Author)value;
if (auth.MiddleName != String.Empty)
{
return String.Format("{0} {1} {2}",
auth.FirstName,
auth.MiddleName,
auth.LastName);
}
else
{
return String.Format("{0} {1}",
auth.FirstName,
auth.LastName);
}
}
return base.ConvertTo(context, culture, value,
destinationType);
}
}
}
代码讨论
AuthorConverter 类的实现阐述了要在 Author 的实例与字符串之间进行双向转换所必须执行的任务:
重写 CanConvertFrom 方法,该方法确定是否可由特定类型创建 Author 实例。如果传入的类型属于 String 类型,则它返回 true。
重写 CanConvertTo 方法,该方法确定 Author 实例是否可以转换为特定类型。如果传入的类型属于 String 类型,则它返回 true。
重写 ConvertFrom 方法,该方法返回一个包含 Author 实例的 FirstName、MiddleName 和 LastName 属性的字符串。
重写 ConvertTo 方法,该方法对包含 Author 实例的串联的 FirstName、MiddleName 和 LastName 属性的字符串进行分析。它返回 Author 类的新实例,其中有来自串联字符串的数据。
生成和使用示例
使用服务器控件属性示例中所述的 Book 控件及其相关类来编译 AuthorConverter 类。
有关编译和使用自定义控件示例的信息,请参见生成自定义服务器控件示例。