TypeConverter学习

之前的一个封装读取配置文件类 中,CommonHelper.To() 方法实现类型的转换,用到了TypeConverter 类。学习记录一下用法。

TypeConverter 实现两个类的互相转换。 通过继承TypeConverter按需实现4个方法来实现自定义类型转换。

 

public virtual object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)

public virtual object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType)

public virtual bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType)

public virtual bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)

 

GenericListTypeConverter.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Globalization;

using System.Linq;



namespace Nop.Core.ComponentModel

{

    public class GenericListTypeConverter<T> : TypeConverter

    {

        protected readonly TypeConverter _typeConverter;



        public GenericListTypeConverter()

        {

            _typeConverter = TypeDescriptor.GetConverter(typeof(T));

            if (_typeConverter == null)

                throw new InvalidOperationException("No type converter exists for type " + typeof(T).FullName);

        }



        protected virtual string[] GetStringArray(string input)

        {

            if (!String.IsNullOrEmpty(input))

            {

                string[] result = input.Split(',');

                Array.ForEach(result, s => s.Trim());

                return result;

            }

            else

                return new string[0];

        }



        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)

        {



            if (sourceType == typeof(string))

            {

                string[] items = GetStringArray(sourceType.ToString());

                return (items.Count() > 0);

            }



            return base.CanConvertFrom(context, sourceType);

        }



        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)

        {

            if (value is string)

            {

                string[] items = GetStringArray((string)value);

                var result = new List<T>();

                Array.ForEach(items, s =>

                {

                    object item = _typeConverter.ConvertFromInvariantString(s);

                    if (item != null)

                    {

                        result.Add((T)item);

                    }

                });



                return result;

            }

            return base.ConvertFrom(context, culture, value);

        }



        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)

        {

            if (destinationType == typeof(string))

            {

                string result = string.Empty;

                if (((IList<T>)value) != null)

                {

                    //we don't use string.Join() because it doesn't support invariant culture

                    for (int i = 0; i < ((IList<T>)value).Count; i++)

                    {

                        var str1 = Convert.ToString(((IList<T>)value)[i], CultureInfo.InvariantCulture);

                        result += str1;

                        //don't add comma after the last element

                        if (i != ((IList<T>)value).Count - 1)

                            result += ",";

                    }

                }

                return result;

            }



            return base.ConvertTo(context, culture, value, destinationType);

        }
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)

        {

            if ((destinationType == typeof(List<T>)) |

                (destinationType == typeof(InstanceDescriptor)))

                return true;

            else

                return base.CanConvertTo(context, destinationType);

        }
   

    }

}

 


Test代码

[Test]

        public void CanConvertFromTest1()

        {

            TypeConverter typeConverter = new GenericListTypeConverter<string>();

            var items = "10,20,30,40,50";

            var list = new List<string>();



            if (typeConverter.CanConvertFrom(typeof(string)))

            {

                list = typeConverter.ConvertFrom(items) as List<string>;

            }

            Assert.AreEqual(list.Count, 5);

        }



        [Test]

        public void CanConvertToTest1()

        {

            var items = new List<string> { "foo", "bar", "day" };

            string result = "";

            TypeConverter typeConverter = new GenericListTypeConverter<string>();

            result = typeConverter.ConvertTo(items, typeof(string)) as string;

            Assert.True(result.Length > 0 );

        }

 

GenericListTypeConverter实现了 string,List<string>的互相转换。

 

上面的代码需要new 一个 TypeConverter方法来实现转换。另一种方法是使用Attribute特性附加在Class中,如下

[TypeConverter(typeof(Triangle.TriangleConverter))]

    public class Triangle

    {

    }

 

这样做方便设计时和运行时实现转换。

//获取该类的TypeConvert实例

var typeConvert =  TypeDescriptor.GetConverter(typeof(Longitude))

 

如果有一下的需求,该如何使用TypeConvert?

1.如何为类库中的类添加特性。

2.根据动态的为类添加TypeConvert。

3.为泛型类添加TypeConvert。

 如下

TypeDescriptor.AddAttributes(typeof(List<string>),

                new TypeConverterAttribute(typeof(GenericListTypeConverter<string>)));

 

Test代码:

[SetUp]

        public void SetUp()

        {

            TypeDescriptor.AddAttributes(typeof(List<int>),

                new TypeConverterAttribute(typeof(GenericListTypeConverter<int>)));

            TypeDescriptor.AddAttributes(typeof(List<string>),

                new TypeConverterAttribute(typeof(GenericListTypeConverter<string>)));

        }



        [Test]

        public void Can_get_int_list_type_converter()

        {

            var converter = TypeDescriptor.GetConverter(typeof(List<int>));

            converter.GetType().ShouldEqual(typeof(GenericListTypeConverter<int>));

        }



        [Test]

        public void Can_get_string_list_type_converter()

        {

            var converter = TypeDescriptor.GetConverter(typeof(List<string>));

            converter.GetType().ShouldEqual(typeof(GenericListTypeConverter<string>));

        }



        [Test]

        public void Can_get_int_list_from_string()

        {

            var items = "10,20,30,40,50";

            var converter = TypeDescriptor.GetConverter(typeof(List<int>));

            var result = converter.ConvertFrom(items) as IList<int>;

            result.ShouldNotBeNull();

            result.Count.ShouldEqual(5);

        }



        [Test]

        public void Can_get_string_list_from_string()

        {

            var items = "foo, bar, day";

            var converter = TypeDescriptor.GetConverter(typeof(List<string>));

            var result = converter.ConvertFrom(items) as List<string>;

            result.ShouldNotBeNull();

            result.Count.ShouldEqual(3);

        }

 

参考:

http://www.cnblogs.com/ericwen/archive/2007/12/12/typeconvertattribute.html

你可能感兴趣的:(Converter)