深度解析 TypeConverter & TypeConverterAttribute (一
点击次数:15 次 发布日期:2008-11-26 10:33:33 作者:源代码网
|
源代码网推荐 前言 源代码网推荐 我们在开发复杂控件的时候不可避免的碰到类型转换TypeConverter,微软给我们提供了很多转换类如ArrayConverter,BaseNumberConverter,BooleanConverter(MSDN上更多:ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref3/html/N_System_ComponentModel.htm)等直接或间接的继承了TypeConverter类。我们在类型转换的时候经常用到这些类。然而我们如何编写自定义的TypeConverter类呢,又怎么样在复杂控件中使用呢。 源代码网推荐 源代码网推荐 TypeConverter Class 源代码网推荐 TypeConverter类就是将一种类型(object,可以说是任何类型)转换到另一种类型(一般为string),或者将另一种类型转换回来。所有继承TypeConverter类型的都必须实现4个方法:(这里以另一种类型string为例) 源代码网推荐 CanConverterTo 有两个重载方法, 源代码网推荐 TypeConverter.CanConvertTo (Type) 源代码网推荐 TypeConverter.CanConvertTo (ITypeDescriptorContext, Type) 源代码网推荐 都有一个Type参数(要转换成什么类型),例如我们设计的要转换成string,在方法体里面判断这个参数的Type如果是string,则返回true,否则返回 false 源代码网推荐 ConverterTo 也有两重载, 源代码网推荐 TypeConverter.ConvertTo (Object, Type) 源代码网推荐 TypeConverter.ConvertTo (ITypeDescriptorContext, CultureInfo, Object, Type) 源代码网推荐 都有Object和Type参数,将Object转成Type类型的Object,返回Type类型的Object。 源代码网推荐 下面类似的两个方法,不过方向相反,是从其他类型装换回来。 源代码网推荐 CanConverterFrom 重载, 源代码网推荐 TypeConverter.CanConvertFrom (Type) 源代码网推荐 TypeConverter.CanConvertFrom (ITypeDescriptorContext, Type) 源代码网推荐 在方法体里面判断参数Type是不是能转换回来的类型,例如string类型,如果是返回true,否则返回false。 源代码网推荐 ConverterFrom 重载, 源代码网推荐 TypeConverter.ConvertFrom (Object) 源代码网推荐 TypeConverter.ConvertFrom (ITypeDescriptorContext, CultureInfo, Object) 源代码网推荐 在方法体里面判断参数Object的类型是不是能转换回来的类型,例如string类型,如果是返回转换回来的类型。 源代码网推荐 源代码网推荐 举例说明,以GPS经纬度位置为例,经纬度位置GPSLocation包括复杂属性经度Longitude和纬度Latitude。现我们根据其一属性Longitude类写个LongtitudeTypeConverter类。 源代码网推荐 首先我们得有个Longtitude类吧。 源代码网推荐 public class Longitude 源代码网推荐 { 源代码网推荐 private int _Degrees; 源代码网推荐 private int _Minutes; 源代码网推荐 private int _Seconds; 源代码网推荐 private LongitudeDirection _Direction; 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 度数 源代码网推荐 /// </summary> 源代码网推荐 public int Degrees { } 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 分度 源代码网推荐 /// </summary> 源代码网推荐 public int Minutes { } 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 秒读 源代码网推荐 /// </summary> 源代码网推荐 public int Seconds { } 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 方向 源代码网推荐 /// </summary> 源代码网推荐 public LongitudeDirection Direction 源代码网推荐 { 源代码网推荐 } 源代码网推荐 }有了个这个类,我们怎样将其转换到string类或其他类呢(这里假设string类)例如“24W3"4”形式,也许你会说重写ToString()方法不就行了,似乎可行,但如果转换成其他类呢,又从其他类转换回来呢,怎么办。还有在复杂控件中Designer设计中又该怎么办。(在复杂控件的应用稍后介绍) 源代码网推荐 自然,这样我们是不是要写个转换类比较好呢,这个类必须直接或这间接继承TypeConverter类。 源代码网推荐 源代码网推荐 class LongitudeTypeConverter : TypeConverter 源代码网推荐 { 源代码网推荐 源代码网推荐 } 源代码网推荐 源代码网推荐 源代码网推荐 然后重载实现上面说的四个方法,现在我要Longitude类转换到string类型 源代码网推荐 源代码网推荐 CanConverterFrom 源代码网推荐 public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 源代码网推荐 { 源代码网推荐 if (sourceType == typeof(string)) 源代码网推荐 return true; 源代码网推荐 else 源代码网推荐 return base.CanConvertFrom(context, sourceType); 源代码网推荐 } 源代码网推荐 CanConverterTo 源代码网推荐 public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 源代码网推荐 { 源代码网推荐 if ((destinationType == typeof(string)) | 源代码网推荐 (destinationType == typeof(InstanceDescriptor))) 源代码网推荐 return true; 源代码网推荐 else 源代码网推荐 return base.CanConvertTo(context, destinationType); 源代码网推荐 } 源代码网推荐 ConvertTo 源代码网推荐 public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) 源代码网推荐 { 源代码网推荐 // check that the value we got passed on is of type Longitude 源代码网推荐 if (value != null) 源代码网推荐 if (!(value is Longitude)) 源代码网推荐 throw new Exception(WrongType); 源代码网推荐 源代码网推荐 // convert to a string 源代码网推荐 if (destinationType == typeof(string)) 源代码网推荐 { 源代码网推荐 // no value so we return an empty string 源代码网推荐 if (value == null) 源代码网推荐 return string.Empty; 源代码网推荐 源代码网推荐 // strongly typed 源代码网推荐 Longitude LongValue = value as Longitude; 源代码网推荐 源代码网推荐 // get the two type converters to use 源代码网推荐 TypeConverter IntConverter = TypeDescriptor.GetConverter(typeof(int)); 源代码网推荐 TypeConverter EnumConverter = TypeDescriptor.GetConverter(typeof(LongitudeDirection)); 源代码网推荐 源代码网推荐 // convert to a string and return 源代码网推荐 return IntConverter.ConvertToString(context, culture, LongValue.Degrees) + 源代码网推荐 EnumConverter.ConvertToString(context, culture, LongValue.Direction).Substring(0, 1) + 源代码网推荐 IntConverter.ConvertToString(context, culture, LongValue.Minutes) + MinutesUnit + 源代码网推荐 IntConverter.ConvertToString(context, culture, LongValue.Seconds) + SecondsUnit; 源代码网推荐 } 源代码网推荐 源代码网推荐 // convert to a instance descriptor 源代码网推荐 if (destinationType == typeof(InstanceDescriptor)) 源代码网推荐 { 源代码网推荐 // no value so we return no instance descriptor 源代码网推荐 if (value == null) 源代码网推荐 return null; 源代码网推荐 源代码网推荐 // strongly typed 源代码网推荐 Longitude LongValue = value as Longitude; 源代码网推荐 源代码网推荐 // used to descripe the constructor 源代码网推荐 MemberInfo Member = null; 源代码网推荐 object[] Arguments = null; 源代码网推荐 源代码网推荐 // get the constructor for the type 源代码网推荐 Member = typeof(Longitude).GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int), typeof(LongitudeDirection) }); 源代码网推荐 源代码网推荐 // create the arguments to pass along 源代码网推荐 Arguments = new object[] { LongValue.Degrees, LongValue.Minutes, LongValue.Seconds, LongValue.Direction }; 源代码网推荐 源代码网推荐 // return the instance descriptor 源代码网推荐 if (Member != null) 源代码网推荐 return new InstanceDescriptor(Member, Arguments); 源代码网推荐 else 源代码网推荐 return null; 源代码网推荐 } 源代码网推荐 源代码网推荐 // call the base converter 源代码网推荐 return base.ConvertTo(context, culture, value, destinationType); 源代码网推荐 } 源代码网推荐 ConvertFrom 源代码网推荐 public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 源代码网推荐 { 源代码网推荐 // no value so we return a new Longitude instance 源代码网推荐 if (value == null) 源代码网推荐 return new Longitude(); 源代码网推荐 源代码网推荐 // convert from a string 源代码网推荐 if (value is string) 源代码网推荐 { 源代码网推荐 // get strongly typed value 源代码网推荐 string StringValue = value as string; 源代码网推荐 源代码网推荐 // empty string so we return a new Longitude instance 源代码网推荐 if (StringValue.Length <= 0) 源代码网推荐 return new Longitude(); 源代码网推荐 源代码网推荐 // get the position of the West longitude separator 源代码网推荐 int DirectionPos = StringValue.IndexOf(LongitudeDirection.West.ToString().Substring(0, 1)); 源代码网推荐 LongitudeDirection Direction = LongitudeDirection.West; 源代码网推荐 源代码网推荐 // if not found get the position of the East longitude separator 源代码网推荐 if (DirectionPos == -1) 源代码网推荐 { 源代码网推荐 DirectionPos = StringValue.IndexOf(LongitudeDirection.East.ToString().Substring(0, 1)); 源代码网推荐 Direction = LongitudeDirection.East; 源代码网推荐 } 源代码网推荐 源代码网推荐 // get the minutes and seconds characters 源代码网推荐 int MinutesPos = StringValue.IndexOf(MinutesUnit); 源代码网推荐 int SecondsPos = StringValue.IndexOf(SecondsUnit); 源代码网推荐 源代码网推荐 // no minutes present 源代码网推荐 if (MinutesPos == -1) 源代码网推荐 throw new Exception(MinutesMissing); 源代码网推荐 源代码网推荐 // no seconds present 源代码网推荐 if (SecondsPos == -1) 源代码网推荐 throw new Exception(SecondsMissing); 源代码网推荐 源代码网推荐 // no minutes present 源代码网推荐 if (DirectionPos == -1) 源代码网推荐 throw new Exception(DirectionMissing); 源代码网推荐 源代码网推荐 // no degrees present 源代码网推荐 if (DirectionPos == 0) 源代码网推荐 throw new Exception(DegreesMissing); 源代码网推荐 源代码网推荐 // get the type converters we need 源代码网推荐 TypeConverter IntConverter = TypeDescriptor.GetConverter(typeof(int)); 源代码网推荐 源代码网推荐 // get the degrees, minutes and seconds value 源代码网推荐 int Degrees = (int)IntConverter.ConvertFromString(context, culture, StringValue.Substring(0, DirectionPos)); 源代码网推荐 int Minutes = (int)IntConverter.ConvertFromString(context, culture, StringValue.Substring(DirectionPos + 1, MinutesPos - DirectionPos - 1)); 源代码网推荐 int Seconds = (int)IntConverter.ConvertFromString(context, culture, StringValue.Substring(MinutesPos + 1, SecondsPos - MinutesPos - 1)); 源代码网推荐 源代码网推荐 // create a new Longitude instance with these values and return it 源代码网推荐 return new Longitude(Degrees, Minutes, Seconds, Direction); 源代码网推荐 } 源代码网推荐 源代码网推荐 // otherwise call the base converter 源代码网推荐 else 源代码网推荐 return base.ConvertFrom(context, culture, value); 源代码网推荐 } 源代码网推荐 有了这个转换类LongitudeTypeConverter,该怎么使用呢。其实很简单就是使用我们上面实现的四个方法, 源代码网推荐 class Test 源代码网推荐 { 源代码网推荐 public static void Main(string[] args) 源代码网推荐 { 源代码网推荐 //将Longitude类转换到string类型 源代码网推荐 Longitude longitude = new Longitude(10,11,12,LongitudeDirection.East); 源代码网推荐 LongitudeTypeConverter converter = new LongitudeTypeConverter(); 源代码网推荐 源代码网推荐 string strLongitude=""; 源代码网推荐 if (converter.CanConvertTo(typeof(string))) 源代码网推荐 { 源代码网推荐 strLongitude = (string)converter.ConvertTo(longitude, typeof(string)); 源代码网推荐 } 源代码网推荐 System.Console.WriteLine(strLongitude); 源代码网推荐 源代码网推荐 //将string还原回Longitude类 源代码网推荐 Longitude longitude1 = new Longitude(); 源代码网推荐 if (converter.CanConvertFrom(typeof(string))) 源代码网推荐 { 源代码网推荐 longitude1 = (Longitude)converter.ConvertFrom(strLongitude); 源代码网推荐 } 源代码网推荐 System.Console.WriteLine(longitude1.Degrees); 源代码网推荐 System.Console.WriteLine(longitude1.Direction); 源代码网推荐 System.Console.WriteLine(longitude1.Minutes); 源代码网推荐 System.Console.WriteLine(longitude1.Seconds); 源代码网推荐 } 源代码网推荐 }输出结果是 源代码网推荐 10E11"12"" 源代码网推荐 10 源代码网推荐 East 源代码网推荐 11 源代码网推荐 12 源代码网推荐 从结果中我们可以看到实现了我们预期的效果。 源代码网推荐 这些在一般代码里面可以用到,但从转换的结果中我们可以联想,web页面设计的两种模式(设计模式,源代码模式),在源代码模式我们显示的是string,但在设计模式我们显示控件的外观,这里就关系到TypeConverter类了,当然还有TypeConverterAtrribute。 源代码网推荐 下面就要说下这个TypeConverterAtrribute了。 做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。 源代码网推荐 源代码网供稿. |
