【问题标题】:How to override NET type converters?如何覆盖 NET 类型转换器?
【发布时间】:2013-10-01 20:02:54
【问题描述】:

我正在开发一个 ETL 类型的应用程序,它从 csv 数据文件创建实体。特别是一个字段 - 布尔字段 - 被证明难以使用,因为系统提供了自己对布尔值的解释,例如 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 并且对于每个公共字段,它通过其键获取字典的项,并尝试将其转换为该字段的基础类型。除了布尔值,它运行良好。

【问题讨论】:

标签: c# type-conversion


【解决方案1】:

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

【讨论】:

  • 由于此答案解决了您问题中的问题,您应该通过单击旁边的复选标记将其标记为已接受的答案。这样人们一眼就能看出问题已经解决了。
  • 光滑!这会覆盖默认类型转换吗?或者它只是添加了另一种转换方式。我希望它只是增加了另一种转换方式
猜你喜欢
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 1970-01-01
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多