How to actually use TypeConverter and how does it differ from System.Convert.ToXXX()
Asked Answered
L

2

10

I've been looking for a more intuitive way of converting between datatypes in C# (like an enum to a string) So i stumbled upon the TypeConverter class. I've read the documentation on how to create one, and it seems fairly straightforward, just override a few methods from TypeConverter with some custom conversion logic and done.

However, ive been unable to figure out how to actually use this converter now that i've created it. every resource I've found simply explains how to create one, and the only reference ive seen to actually using it is decorating my type class with [TypeConverter(typeof(MyConverter))]. The problem is I dont actually have a type class, my type im converting to/from is an enum and string, so i have no idea where im supposed to put the TypeConverter.

Hypothetically if my type was a custom class, and I put the decoration just on the class where its defined, how would I then convert the type? Do I just use the type as a string wherever i want and the converter will magically do its work without being asked or do i need to prompt it somehow. Is there a scope within which I can use the type converter or is it accessible anywhere that the type is?

I was kind of expecting this to work like System.Convert, but that doesnt seem to be the case.

Larousse answered 26/3, 2018 at 8:37 Comment(5)
Never used it, but there is also a more specific class EnumConverter which inherit from TypeConverter.Dysphagia
@Dysphagia EnumConverter is used automatically as the default converter for all enums, IIRCBobolink
I'm guessing a "simple" enumValue.ToString() and EnumType enumValue; EnumValue.TryParse("StringValue", out enumValue); won't suffice?Dysphagia
TypeConverter powers the PropertyGrid class and the Properties window in Visual Studio. Its principal job is to convert a type to strings that make sense to a human. Winforms is its biggest customer. It can be pretty handy in your own code as well, but you have to understand its domain. If the type is your own instead of one from the framework and you don't use stringly typing or care about localization then having to write your own TypeConverter rarely puts you ahead, it just becomes an extra layer of complexity that you don't need.Limbourg
enumValue.ToString() actually does work, and is all I need for this situation. I didnt even think of trying it because I was under the impression that enums were only available as a static list of integers during run-time.Larousse
B
13

An enum is still a custom type and can still have attributes such as [TypeConverter].

Only a small number of APIs use TypeConverter; in particular, this means System.ComponentModel, which is what drives things like PropertyGrid, so: you don't get it everywhere automatically, but it can still be useful in some cases. The main intended way of getting the converter is:

var conv = TypeDescriptor.GetConverter(obj);

which allows it to work with attributes (which you've found), but also ICustomTypeDescriptor and TypeDescriptor, via TypeDescriptor.GetProvider / TypeDescriptor.AddProvider. It is a very confusing but flexible model for dynamically describing data.

In most scenarios, however, TypeConverter is not usually the way to implement things. As a barely working example:

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);
    }
}

However, it probably makes more sense - as noted previously - when mixed with things like PropertyGrid or other UI elements.

It is very different to the methods on Convert.*, as that is not an extensible model. System.ComponentModel can be tweaked at runtime, and used with objects that at the object level (not the type level) describe themselves. The main usage of this was for things like DataTable, so that a row can act as though it has properties named for each column - via PropertyDescriptor rather than PropertyInfo (reflection).

Bobolink answered 26/3, 2018 at 8:49 Comment(2)
So this sounds like its pretty closely related to PropertyGrid and WinForms? I skipped WinForms in favor of WPF, but would TypeConverter be in any way comparable to a WPF valueconverter?Larousse
@Larousse you're right that there's a strong relationship between winforms and TypeConverter. I don't know much about WPF, so I can't comment with confidence, but I suspect that they're similar concepts, with entirely unrelated implementations.Bobolink
E
0

I can't help with TypeConverter but you can get a list of names from an enum fairly directly:

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

To get the enum value from its name/string representation:

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

Eckel answered 26/3, 2018 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.