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

  • 相关阅读:
    jsp 页面获取当前路径
    html5 页面音频
    微信关于网页授权access_token和普通access_token的区别
    Texlive source
    vscode 快捷键
    vscode setting
    vscode extension 插件管理
    what
    linux manual
    java tool type
  • 原文地址:https://www.cnblogs.com/miku/p/2698333.html
Copyright © 2011-2022 走看看