如何覆盖NET类型转换器? [英] How to override NET type converters?

查看:81
本文介绍了如何覆盖NET类型转换器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从CSV数据文件创建一个实体ETL类型的应用程序。一个特别的领域 - 一个布尔字段 - 被证明是很难用,因为系统提供自己一个布尔值的解释,如真,假,是,否,1,0,甚至-1等

I'm working on an ETL-type application which creates entities from csv data files. One field in particular - a boolean field - is proving difficult to work with because systems provide their own interpretation of a bool such as true, false, yes, no, 1, 0 or even -1 etc.

使用默认的类型转换器大多数测试失败:

Using the default type converters most of the tests fail:

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,这样我可以提供我的自己的解析器正确处理上面。任何想法如何做到这一点?

What I would like to do is override the default System.ComponentModel.BooleanConverter so that I can provide my own parser to correctly handle above. Any idea how to do this?

帖子由Scott Hanselman在触及到创建的类型转换器,但我希望覆盖默认的。

This post by Scott Hanselman touches on creating type converters but I wish to override the default one.

有关参考这里是我的实体提取的实现。

For reference here's my entity extractor implementation.

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并为每个公共领域它获得了字典的项目由它的键并试图将其转换为场的基础类型。除了布尔变量它运作良好。

Basically it enumerates a given TEntity and for each public field it obtains the dictionary's item by its key and attempts to convert it to the field's underlying type. It is working well except for bools.

推荐答案

感谢的阿萨德中我创建了一个自定义的类型转换器

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's startup:

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

现在用修改后的代码提取,每个属性使用正确的类型转换器。通常情况下,这将是内置的转换器之一,但由于BoolTypeConverter的类型布尔登记,这是用来代替。

Now with the modified extractor code, for each property the correct type converter is used. Normally this would be one of the built-in converters, but because of the registration of BoolTypeConverter for type boolean, 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;
}

这篇关于如何覆盖NET类型转换器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆