在上一篇文章,我為控件添加一個一個復雜屬性,並且為這個屬性的類型的編寫了一個類型轉換器, 現在我們來看看這個類型轉換器的代碼,並解釋一下這些代碼的意義。
要實現一個類型轉換器,我們必須要重寫(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”,由於沒有輸入“,”,我 們無法將屬性的值分拆為兩個字符串,也就無法進行下面的轉換,所以,我們要拋出一個異常,通知用戶 重新輸入。