Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use TypeConverters with a ConfigurationSection?

So I've got a ConfigurationSection/ConfigurationElementCollection that has a configuration like this:

<mimeFormats>
    <add mimeFormat="text/html" />
</mimeFormats>

And here is how I handle the mimeFormats:

 public class MimeFormatElement: ConfigurationElement
{
    #region Constructors
    /// <summary>
    /// Predefines the valid properties and prepares
    /// the property collection.
    /// </summary>
    static MimeFormatElement()
    {
        // Predefine properties here
        _mimeFormat = new ConfigurationProperty(
            "mimeFormat",
            typeof(MimeFormat),
            "*/*",
            ConfigurationPropertyOptions.IsRequired
        );
    }
    private static ConfigurationProperty _mimeFormat;
    private static ConfigurationPropertyCollection _properties;

    [ConfigurationProperty("mimeFormat", IsRequired = true)]
    public MimeFormat MimeFormat
    {
        get { return (MimeFormat)base[_mimeFormat]; }
    }
}

public class MimeFormat
{
    public string Format
    {
        get
        {
            return Type + "/" + SubType;
        }
    }
    public string Type;
    public string SubType;

    public MimeFormat(string mimeFormatStr)
    {
        var parts = mimeFormatStr.Split('/');
        if (parts.Length != 2)
        {
            throw new Exception("Invalid MimeFormat");
        }

        Type = parts[0];
        SubType = parts[1];
    }
}

And obviously I need a TypeConverter that actually does something (instead of this empty shell):

public class MimeFormatConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        throw new NotImplementedException();
    }
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        throw new NotImplementedException();
    }
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        throw new NotImplementedException();
    }
}

How do I set up a TypeConverter that will allow type conversion from/to string? I've tried using the MSDN examples but I keep getting error message:

TypeConverter cannot convert from System.String.

Essentially, how can it be set up so that it will just work with whatever ConfigurationSection is trying to do?

like image 347
David Murdoch Avatar asked May 09 '11 16:05

David Murdoch


3 Answers

You can put TypeConverterAttribute on the property to tell the serializer how to handle it.

[TypeConverter(typeof(MimeFormatConverter))]
[ConfigurationProperty("mimeFormat", IsRequired = true)]
public MimeFormat MimeFormat
{
    get { return (MimeFormat)base[_mimeFormat]; }
}
like image 54
Joe B Avatar answered Nov 17 '22 00:11

Joe B


Try this:

TestSection.cs

public class TestSection : ConfigurationSection
{

    private static readonly ConfigurationProperty sFooProperty = new ConfigurationProperty("Foo",
                                                                                          typeof(Foo),
                                                                                          null,
                                                                                          new FooTypeConverter(),
                                                                                          null,
                                                                                          ConfigurationPropertyOptions.None);

    public static readonly ConfigurationPropertyCollection sProperties = new ConfigurationPropertyCollection();

    static TestSection()
    {
        sProperties.Add(sFooProperty);
    }

    public Foo Foo
    {
        get { return (Foo)this[sFooProperty]; }
        set { this[sFooProperty] = value; }
    }

    protected override ConfigurationPropertyCollection Properties
    {
        get { return sProperties; }
    }

}

Foo.cs

public class Foo
{

    public string First { get; set; }
    public string Second { get; set; }

    public override string ToString()
    {
        return First + ',' + Second;
    }

}

FooTypeConverter.cs

public class FooTypeConverter : TypeConverter
{

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return (sourceType == typeof(string));
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        string val = value as string;

        if (val != null)
        {
            string[] parts = val.Split(',');

            if (parts.Length != 2)
            {
                // Throw an exception
            }

            return new Foo { First = parts[0], Second = parts[1] };
        }

        return null;
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return (destinationType == typeof(string));
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        Foo val = value as Foo;

        if (val != null)
            return val.ToString();

        return null;
    }

}
like image 30
Mehdi Golchin Avatar answered Nov 16 '22 23:11

Mehdi Golchin


I figured it out. Here is the solution:

public class MimeFormatElement: ConfigurationElement
{
    #region Constructors
    /// <summary>
    /// Predefines the valid properties and prepares
    /// the property collection.
    /// </summary>
    static MimeFormatElement()
    {
        // Predefine properties here
        _mimeFormat = new ConfigurationProperty(
            "mimeFormat",
            typeof(MimeFormat),
            "*/*",
            ConfigurationPropertyOptions.IsRequired
        );

        _properties = new ConfigurationPropertyCollection {
            _mimeFormat, _enabled
        };
    }
    private static ConfigurationProperty _mimeFormat;
    private static ConfigurationPropertyCollection _properties;

    [ConfigurationProperty("mimeFormat", IsRequired = true)]
    public MimeFormat MimeFormat
    {
        get { return (MimeFormat)base[_mimeFormat]; }
    }
}

/*******************************************/
[TypeConverter(typeof(MimeFormatConverter))]
/*******************************************/
public class MimeFormat
{
    public string Format
    {
        get
        {
            return Type + "/" + SubType;
        }
    }
    public string Type;
    public string SubType;

    public MimeFormat(string mimeFormatStr)
    {
        var parts = mimeFormatStr.Split('/');
        if (parts.Length != 2)
        {
            throw new Exception("Invalid MimeFormat");
        }

        Type = parts[0];
        SubType = parts[1];
    }
}

public class MimeFormatConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string);
    }
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        return new MimeFormat((string)value);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(string);
    }
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        var val = (MimeFormat)value;
        return val.Type + "/" + val.SubType;
    }
}
like image 1
David Murdoch Avatar answered Nov 16 '22 23:11

David Murdoch