在上一篇文章,我為控件添加一個一個復雜屬性,並且為這個屬性的類型的編寫了一個類型轉換器, 現在我們來看看這個類型轉換器的代碼,並解釋一下這些代碼的意義。
要實現一個類型轉換器,我們必須要重寫(override)四個方法:
CanConvertFrom()――根據類型參數進行測試,判斷是否能從這個類型轉換成當前類型,在本例中我 們只提供轉換string和InstanceDescriptor類型的能力。
CanConvertTo()――根據類型參數進行測試,判斷是否能從當前類型轉換成指定的類型。
ConvertTo()――將參數value的值轉換為指定的類型。
ConvertFrom()――串換參數value,並返回但書類型的一個對象。
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destinationType)
{
String result = "";
if (destinationType == typeof(String))
{
Scope scope = (Scope)value;
result = scope.Min.ToString()+"," + scope.Max.ToString();
return result;
}
if (destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ci = typeof(Scope).GetConstructor(new Type[]
{typeof(Int32),typeof(Int32) });
Scope scope = (Scope)value;
return new InstanceDescriptor(ci, new object[] {
scope.Min,scope.Max });
}
return base.ConvertTo(context, culture, value, destinationType);
}
上面是ConvertTo的實現,如果轉換的目標類型是string,我將Scope的兩個屬性轉換成string類型, 並且用一個“,”連接起來,這就是我們在屬性浏覽器裡看到的表現形式,如圖:

如果轉換的目標類型是實例描述器(InstanceDescriptor,它負責生成實例化的代碼),我們需要構 造一個實例描述器,構造實例描述器的時候,我們要利用反射機制獲得Scope類的構造器信息,並在new的 時候傳入Scope實例的兩個屬性值。實例描述器會為我們生成這樣的代碼:this.myListControl1.Scope = new CustomControlSample.Scope(10, 200);在最後不要忘記調用 base.ConvertTo(context, culture, value, destinationType),你不需要處理的轉換類型,交給基類去做好了。
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
if (value is string)
{
String[] v = ((String)value).Split(',');
if (v.GetLength(0) != 2)
{
throw new ArgumentException("Invalid parameter
format");
}
Scope csf = new Scope();
csf.Min = Convert.ToInt32(v[0]);
csf.Max = Convert.ToInt32(v[1]);
return csf;
}
return base.ConvertFrom(context, culture, value);
}
}
上面是ConvertFrom的代碼,由於系統能夠直接將實例描述器轉換為Scope類型,所以我們就沒有必要 再寫代碼,我們只需要關注如何將String(在屬性浏覽出現的屬性值的表達)類型的值轉換為Scope類型 。沒有很復雜的轉換,只是將這個字符串以“,”分拆開,並串換為Int32類型,然後new一個Scope類的 實例,將分拆後轉換的兩個整型值賦給Scope的實例,然後返回實例。在這段代碼裡,我們要判斷一下用 戶設定的屬性值是否有效。比如,如果用戶在Scope屬性那裡輸入了“10200”,由於沒有輸入“,”,我 們無法將屬性的值分拆為兩個字符串,也就無法進行下面的轉換,所以,我們要拋出一個異常,通知用戶 重新輸入。