zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    POJ 3710 Christmas Game#经典图SG博弈
    POJ 2599 A funny game#树形SG(DFS实现)
    POJ 2425 A Chess Game#树形SG
    LeetCode Array Easy 122. Best Time to Buy and Sell Stock II
    LeetCode Array Easy121. Best Time to Buy and Sell Stock
    LeetCode Array Easy 119. Pascal's Triangle II
    LeetCode Array Easy 118. Pascal's Triangle
    LeetCode Array Easy 88. Merge Sorted Array
    ASP.NET MVC 学习笔记之 MVC + EF中的EO DTO ViewModel
    ASP.NET MVC 学习笔记之面向切面编程与过滤器
  • 原文地址:https://www.cnblogs.com/miku/p/2698333.html
Copyright © 2011-2022 走看看