How to override NET type converters?

I am working on an application such as ETL that creates entities from csv data files. One field, in particular a logical field, is difficult to work because systems provide their own interpretation of bool, for example true, false, yes, no, 1, 0 or even -1, etc.

Using standard type converters, most tests do not work:

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); 

What I would like to do is to override the standard System.ComponentModel.BooleanConverter so that I can provide my own parser for the correct processing above. Any idea how to do this?

This post by Scott Hanselman addresses the creation of type converters, but I want to override the default value.

For reference, here is my implementation of an entity extractor.

 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; } 

Basically, he lists a specific TEntity and for each open field he gets a dictionary element with his key and tries to convert it to the type that underlies the field. It works well except for bools.

+6
source share
1 answer

Thanks to Asad, I created a custom 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); } } 

And registered in the program launch:

 TypeDescriptor.AddAttributes(typeof(Boolean), new TypeConverterAttribute(typeof(BoolTypeConverter))); 

Now with the changed extractor code, the correct type converter is used for each property. Usually this will be one of the built-in converters, but due to the registration of the BoolTypeConverter for the boolean type, this is used instead.

 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; } 
+4
source

Source: https://habr.com/ru/post/954648/


All Articles