转换器


  IValueConverter 接口定义了数据转换的规则,它提供两个方法:

  • ConvertFrom 方法将数据库支持的数据类型转换为对象

  • ConvertTo 方法将对象转换可数据库支持的数据类型

  下例演示了对于 System.Drawing.Color 如何存储和读取的:

public sealed class ColorConverter : IValueConverter
{
    public object ConvertFrom(object value, DbType dbType = DbType.String)
    {
        switch (dbType)
        {
            case DbType.String:
            case DbType.StringFixedLength:
            case DbType.AnsiString:
            case DbType.AnsiStringFixedLength:
                return ConvertFromString(value);
            case DbType.Binary:
                return ConvertFromBinary(value);
            default:
                throw new ConverterNotSupportedException(typeof(Color), dbType);
        }
    }

    public object ConvertTo(object value, DbType dbType = DbType.String)
    {
        switch (dbType)
        {
            case DbType.String:
            case DbType.StringFixedLength:
            case DbType.AnsiString:
            case DbType.AnsiStringFixedLength:
                return ConvertToString(value);
            case DbType.Binary:
                return ConvertToBinary(value);
            default:
                throw new ConverterNotSupportedException(typeof(Color), dbType);
        }
    }

    private object ConvertFromString(object value)
    {
        if (value.IsNullOrEmpty())
        {
            return Color.Empty;
        }

        var converter = TypeDescriptor.GetConverter(typeof(int));
        if (converter == null)
        {
            return Color.Empty;
        }

        var val = converter.ConvertFromString("0x" + value);
        return val == null ? Color.Empty : Color.FromArgb(-16777216 | (int)val);
    }

    private object ConvertFromBinary(object value)
    {
        var bytes = (byte[])value;
        if (bytes == null)
        {
            return Color.Empty;
        }

        return bytes.Length switch
        {
            4 => Color.FromArgb(bytes[0], bytes[1], bytes[2], bytes[3]),
            3 => Color.FromArgb(bytes[0], bytes[1], bytes[2]),
            _ => Color.Empty,
        };
    }

    private object ConvertToString(object value)
    {
        if (value == null || string.IsNullOrEmpty(value.ToString()))
        {
            return string.Empty;
        }

        var color = (Color)value;
        return string.Format(
            "{0}{1}{2}{3}",
            color.A.ToString("X2"),
            color.R.ToString("X2"),
            color.G.ToString("X2"),
            color.B.ToString("X2"));
    }

    private object ConvertToBinary(object value)
    {
        if (value == null)
        {
            return new byte[0];
        }

        var color = (Color)value;
        return new[] { color.A, color.R, color.G, color.B };
    }
}

  从上面的示例中可以看出,System.Drawing.Color 可以使用字符串和二进制进行存储,两个方法的 dbType 参数即指定了字段的数据类型,针对不同的数据类型,对存储和读取都做了处理。

  ValueConverterBase<T> 是一个泛型抽象类,如果你需要扩展其他的转换器,可以继承自它。