我正在开发一个ETL类型的应用程序,它从csv数据文件创建实体。特别是一个字段 - 一个布尔字段 - 证明难以使用,因为系统提供了他们自己对bool的解释,如true,false,yes,no,1,0,甚至-1等。
使用默认类型转换器,大多数测试都失败了:
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,并且对于每个公共字段,它通过其键获取字典的项目并尝试将其转换为字段的基础类型。除了布尔之外,它运作良好。
答案 0 :(得分: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的注册类型为boolean,因此使用它。
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;
}