2013-09-26 48 views
6

我正在研究一個從csv數據文件創建實體的ETL類型的應用程序。特別是一個字段 - 一個布爾字段 - 由於系統提供了他們自己對bool的解釋,例如true,false,yes,no,1,0甚至-1等,所以很難處理。如何覆蓋NET類型轉換器?

使用default類型轉換器大多數測試失敗:

var b1 = Convert.ChangeType("true", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b2 = Convert.ChangeType("false", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b3 = Convert.ChangeType("True", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b4 = Convert.ChangeType("False", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b5 = Convert.ChangeType("TRUE", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b6 = Convert.ChangeType("FALSE", TypeCode.Boolean, CultureInfo.InvariantCulture); 

// All below fail 
var b7 = Convert.ChangeType("yes", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b8 = Convert.ChangeType("no", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b9 = Convert.ChangeType("Yes", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b10 = Convert.ChangeType("No", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b11 = Convert.ChangeType("YES", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b12 = Convert.ChangeType("NO", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b13 = Convert.ChangeType("1", TypeCode.Boolean, CultureInfo.InvariantCulture); 
var b14 = Convert.ChangeType("0", TypeCode.Boolean, CultureInfo.InvariantCulture); 

我想要做的是覆蓋默認System.ComponentModel.BooleanConverter,這樣我可以提供我自己的解析器以上正確處理。任何想法如何做到這一點?

Scott Hanselman的post涉及創建類型轉換器,但我希望覆蓋默認值。

這裏是我的實體提取器的實現。

public static TEntity ExtractEntity<TEntity>(Dictionary<string, string> row) where TEntity : class 
{ 
    var entity = Activator.CreateInstance<TEntity>(); 
    var entityType = typeof(TEntity); 

    foreach (var info in entityType.GetProperties()) 
    { 
     try 
     { 
      info.SetValue(
       entity, 
       Convert.ChangeType(row[info.Name], info.PropertyType, CultureInfo.InvariantCulture), 
       null); 
     } 
     catch {} 
    } 

    return entity; 
} 

基本上它列舉了給定TEntity併爲每個公共字段它通過其密鑰獲取字典的項目,並嘗試將其轉換成該字段的基礎類型。它除了布爾之外運作良好。

+2

你可以註冊使用屬性的bool自定義類型轉換器,然後用'TypeDescriptor.GetConverter(info.PropertyType)',它總是在默認返回你的類型轉換器。在使用之前,使用生成的轉換器將您的值轉換爲'info.PropertyType'。 –

+0

可能重複[是否可以重寫現有.net類型的類型描述符?](http://stackoverflow.com/questions/4713177/is-it-possible-to-override-the-type-descriptor-現有網絡類型) –

回答

4

感謝Asad我創建了一個自定義的TypeConverter

class BoolTypeConverter : TypeConverter 
{ 
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
    { 
     if (destinationType == typeof (bool)) 
     { 
      return true; 
     } 
     return base.CanConvertTo(context, destinationType); 
    } 

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
    { 
     if (value is string) 
     { 
      var s = value as string; 
      if (string.IsNullOrEmpty(s)) 
       return false; 
      switch (s.Trim().ToUpper()) 
      { 
       case "TRUE": 
       case "YES": 
       case "1": 
       case "-1": 
        return true; 

       default: 
        return false; 
      } 
     } 
     return base.ConvertTo(context, culture, value, destinationType); 
    } 
} 

並在程序的啓動註冊:

TypeDescriptor.AddAttributes(typeof(Boolean), 
new TypeConverterAttribute(typeof(BoolTypeConverter))); 
與修改後的提取碼

現在,每個屬性使用正確的類型轉換器。通常情況下,這將是內置轉換器之一,但由於BoolTypeConverter類型布爾值的註冊,所以可以使用它。

public static TEntity ExtractEntity<TEntity>(Dictionary<string, string> row) where TEntity : class 
{ 
    var entity = Activator.CreateInstance<TEntity>(); 
    var entityType = typeof(TEntity); 

    foreach (var info in entityType.GetProperties()) 
    { 
     try 
     { 
      var converter = TypeDescriptor.GetConverter(info.PropertyType); 
      if (!converter.CanConvertTo(info.PropertyType)) continue; 

      info.SetValue(entity, converter.ConvertTo(row[info.Name], info.PropertyType)); 
     } 
     catch {} 
    } 

    return entity; 
} 
+0

由於此答案解決了您的問題中的問題,因此應通過單擊旁邊的複選標記將其標記爲已接受的答案。這樣人們可以一眼就知道問題已經解決。 –

+0

華麗!這是否會覆蓋默認的類型轉換?或者它只是添加另一種轉換方式。我希望它只是增加了另一種轉換方式 – matrixugly