mbp
mbp

Reputation: 91

C# TypeConverter.ConvertFrom() problem

I have a problem with the following code which returns an object from a string:

[TypeConverter(typeof(MyConverter))]
public class MyClass
{
    public string s;
}

public class MyConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return (sourceType == typeof(string)) ? true : base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string)
        {
            MyClass m = new MyClass();
            m.s = (string)value;
            return m;
        }

        return base.ConvertFrom(context, culture, value);
    }
}

When I try to use with this code:

string s_test = "test";

MyClass m_test;

m_test = (MyClass)Convert.ChangeType(s_test, typeof(MyClass));

I get the error message

Invalid cast from 'System.String' to 'MyClass'.

What is wrong in my code? Note that I must use the ConvertFrom() method...

Thank you in advance for your help.

Stack trace:

[InvalidCastException: Invalid cast from 'System.String' to 'MyClass'.]
   System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) +9496632
   System.String.System.IConvertible.ToType(Type type, IFormatProvider provider) +8
   System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) +9531720
   System.Convert.ChangeType(Object value, Type conversionType) +32
   OrderController.Index() in [...].cs:70
   ... omitted for brevity ...

Upvotes: 1

Views: 7532

Answers (5)

Richard Petheram
Richard Petheram

Reputation: 845

(Found this link while searching for the answer to a similar question, so posting the best answer I found)

The implicit and explicit operators seem to be what you want, TypeConverter isn't needed

public class MyClass
{
    public string s;

    public static explicit operator MyClass(string s) {
        MyClass m = new MyClass();
        m.s = (string)value;
        return m;
    }
}

Which allows the following:-

string s_test = "test";

MyClass m_test;

m_test = (MyClass)s_test;

Note: The above is untested, but should be close enough to give the needed clues.

Upvotes: 2

Antoine Aubry
Antoine Aubry

Reputation: 12469

The SixPack library has a TypeConverter class that supports most of the .NET conversion methods, including TypeConverter. The conversions that are supported are the following:

  • TypeConverter on source type
  • TypeConverter on destination type
  • C# explicit and implicit casting operators
  • IConvertible

There is also special treatment of the following types

  • DbNull
  • Nullable
  • Enum
  • TimeSpan

Upvotes: 0

pstrjds
pstrjds

Reputation: 17448

Building off of the correct answer from Jon Skeet, you need to use the TypeDescriptor to do the conversion. Change your test code from:

string s_test = "test";
MyClass m_test;
m_test = (MyClass)Convert.ChangeType(s_test, typeof(MyClass));

To:

string s_test = "test";
MyClass m_test;
m_test = (MyClass)TypeDescriptor.GetConverter(typeof(MyClass)).ConvertFromString(test);

and all should be well.

Upvotes: 3

Ben Voigt
Ben Voigt

Reputation: 283773

You seem to be under the impression that Convert.ChangeType looks for a TypeConverter. It doesn't.

From the MSDN doc: "For the conversion to succeed, value must implement the IConvertible interface"

Since System.String doesn't implement IConverter<MyClass>, you're out of luck (with the Convert class, anyway). Like Skeet said (and MSDN), use TypeDescriptor instead.

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1502536

You're expecting Convert.ChangeType to use a TypeConverter if one is present - it doesn't. TypeConverter is usually used in conjunction with TypeDescriptor (often implicitly in UI frameworks).

Upvotes: 8

Related Questions