开发者

How can I use TypeConverters with a ConfigurationSection?

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

<mimeF开发者_运维知识库ormats>
    <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?


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


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

}


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


From this point, you have to create the convert sections within the ConvertTo and ConvertFrom methods

public override object ConvertFrom( ITypeDescriptorContext context, CultureInfo culture, object value ) {
  if ( value == null )
    return null;

  try {
    if ( value is string ) {
      string s = (string)value;

      // here is where you look at the string to figure out the MimeFormat
      // like so....
      return new MimeFormat( s );
    }


  throw new NotSupportedException( NotSupportedException( value.GetType(), typeof(MimeFormat) );
}

public override object ConvertTo( ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType ) {
  if ( value == null )
    return null;

  MimeFormat p = (MimeFormat)value;
  if ( destinationType == typeof( String ) )
    return p.ToString();

  throw new NotSupportedException( NotSupportedException( typeof(MimeFormat), destinationType ) );
}

EDITED

You also need to override the CanConvert functions as well.

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

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜