【问题标题】:How to actually use TypeConverter and how does it differ from System.Convert.ToXXX()如何实际使用 TypeConverter 以及它与 System.Convert.ToXXX() 有何不同
【发布时间】:2018-03-26 08:37:48
【问题描述】:

我一直在寻找一种更直观的方式在 C# 中的数据类型之间进行转换(比如枚举到字符串),所以我偶然发现了 TypeConverter 类。我已经阅读了有关如何创建一个的文档,它看起来相当简单,只需使用一些自定义转换逻辑覆盖 TypeConverter 中的一些方法并完成。

但是,既然我已经创建了这个转换器,我就无法弄清楚如何实际使用它。我发现的每一个资源都简单地解释了如何创建一个,而我看到实际使用它的唯一参考是用[TypeConverter(typeof(MyConverter))] 装饰我的类型类。问题是我实际上没有类型类,我转换到/从的类型是枚举和字符串,所以我不知道我应该把 TypeConverter 放在哪里。

假设我的类型是自定义类,并且我将装饰放在定义它的类上,那么我将如何转换类型?我只是在任何我想要的地方使用类型作为字符串,转换器会神奇地完成它的工作而不会被询问,还是我需要以某种方式提示它。是否有可以使用类型转换器的范围,还是可以在该类型所在的任何地方访问它?

我有点期待它可以像 System.Convert 一样工作,但事实并非如此。

【问题讨论】:

  • 没用过,不过还有一个更具体的类EnumConverter继承自TypeConverter
  • @Corak EnumConverter 自动用作所有枚举 IIRC 的默认转换器
  • 我猜一个“简单的”enumValue.ToString()EnumType enumValue; EnumValue.TryParse("StringValue", out enumValue); 不够?
  • TypeConverter 为 Visual Studio 中的 PropertyGrid 类和“属性”窗口提供支持。它的主要工作是将类型转换为对人类有意义的字符串。 Winforms 是其最大的客户。它在你自己的代码中也很方便,但你必须了解它的领域。如果类型是您自己的而不是框架中的类型,并且您不使用字符串类型或关心本地化,那么必须编写自己的 TypeConverter 很少会让您领先,它只会成为您不需要的额外复杂层.
  • enumValue.ToString() 实际上确实有效,这就是我在这种情况下所需要的。我什至没有想过尝试它,因为我的印象是枚举在运行时只能作为静态整数列表使用。

标签: c# typeconverter


【解决方案1】:

枚举仍然是自定义类型,仍然可以具有[TypeConverter] 等属性。

只有少数 API 使用TypeConverter;特别是,这意味着System.ComponentModel,它是驱动诸如PropertyGrid 之类的东西的原因,所以:你不会在任何地方自动得到它,但在某些情况下它仍然很有用。获取转换器的主要预期方式是:

var conv = TypeDescriptor.GetConverter(obj);

这允许它使用属性(您已经找到),但也可以使用ICustomTypeDescriptorTypeDescriptor,通过TypeDescriptor.GetProvider / TypeDescriptor.AddProvider。这是一个非常混乱但灵活的模型,用于动态描述数据。

然而,在大多数情况下,TypeConverter 通常不是实现事物的方式。作为一个勉强的例子:

using System;
using System.ComponentModel;
using System.Globalization;

static class P
{
    static void Main()
    {
        var foo = Foo.Gamma;
        var converter = TypeDescriptor.GetConverter(typeof(Foo));
        string s = converter.ConvertToString(foo);
        Console.WriteLine(s);
    }
}

[TypeConverter(typeof(FooConverter))]
public enum Foo
{
    Alpha, Beta, Gamma
}
class FooConverter : TypeConverter
{
    public override object ConvertTo(ITypeDescriptorContext context,
        CultureInfo culture, object value, Type destinationType)
    {
        // write it backwards, because: reasons
        if (destinationType == typeof(string)) {
            var s = value.ToString();
            char[] c = s.ToCharArray();
            Array.Reverse(c);
            return new string(c);
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

但是,如前所述,当与 PropertyGrid 或其他 UI 元素等内容混合时,它可能更有意义。

它与Convert.* 上的方法非常不同,因为那不是可扩展的模型。 System.ComponentModel 可以在运行时调整,并与在对象级别(不是类型级别)描述自己的对象一起使用。它的主要用途是用于DataTable 之类的东西,这样一行就可以表现得好像它具有为每一列命名的属性——通过PropertyDescriptor 而不是PropertyInfo(反射)。

【讨论】:

  • 所以这听起来与 PropertyGrid 和 WinForms 密切相关?我跳过 WinForms 转而使用 WPF,但是 TypeConverter 是否可以与 WPF valueconverter 相媲美?
  • @Olli 你说得对,winforms 和 TypeConverter 之间有很强的关系。我对 WPF 了解不多,因此无法自信地发表评论,但我怀疑它们是相似的概念,具有完全不相关的实现。
【解决方案2】:

我对 TypeConverter 无能为力,但您可以直接从枚举中获取名称列表:

List<string> pageSizes = Enum.GetNames(typeof(PageSize)).ToList();

从其名称/字符串表示中获取枚举值:

this.PageSize = (PageSize)Enum.Parse(typeof(PageSize), "A4")

【讨论】:

    猜你喜欢
    • 2016-12-09
    • 2016-02-01
    • 2018-11-07
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 2010-12-31
    • 2020-04-08
    • 2012-02-09
    相关资源
    最近更新 更多