Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 405
Olli Avatar asked Mar 26 '18 08:03

Olli


1 Answers

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).

like image 106
Marc Gravell Avatar answered Nov 13 '22 05:11

Marc Gravell