Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a TypeConverter be used for constructor argument

I'm trying to write a markupextension like this:

[MarkupExtensionReturnType(typeof(Length))]
public class LengthExtension : MarkupExtension
{
    // adding the attribute like this compiles but does nothing.
    public LengthExtension([TypeConverter(typeof(LengthTypeConverter))]Length value)
    {
        this.Value = value;
    }

    [ConstructorArgument("value")]
    public Length Value { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this.Value;
    }
}

To be used like this:

<Label Content="{units:Length 1 mm}" />

Errs with:

The TypeConverter for type "Length" does not support converting from string.

The TypeConverter works if I:

  • Put it on the Valueproperty and have a default ctor.
  • Decorate the Length type with the attribute.

While this may be x/y I don't want any of those solutions.

Here is the code for the converter:

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

        return base.CanConvertFrom(context, sourceType);
    }

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

        return base.CanConvertTo(context, destinationType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        var text = value as string;
        if (text != null)
        {
            return Length.Parse(text, culture);
        }

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

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (value is Length && destinationType != null)
        {
            var length = (Length)value;
            if (destinationType == typeof(string))
            {
                return length.ToString(culture);
            }
            else if (destinationType == typeof(InstanceDescriptor))
            {
                var factoryMethod = typeof(Length).GetMethod(nameof(Length.FromMetres), BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(double) }, null);
                if (factoryMethod != null)
                {
                    var args = new object[] { length.metres };
                    return new InstanceDescriptor(factoryMethod, args);
                }
            }
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }
}
like image 535
Johan Larsson Avatar asked Jan 28 '16 15:01

Johan Larsson


2 Answers

From MSDN, Applying the TypeConverterAttribute (emphasis mine):

In order for your custom type converter to be used as the acting type converter for a custom class by a XAML processor, you must apply the .NET Framework attribute TypeConverterAttribute to your class definition...

and

You can also provide a type converter on a per-property basis. Instead of applying a .NET Framework attribute TypeConverterAttribute to the class definition, apply it to a property definition...

No mention of any other place to apply the attribute. So the answer to your question is very likely

No, a TypeConverter can not be used for a constructor argument.

like image 153
Clemens Avatar answered Sep 22 '22 15:09

Clemens


Posting this for criticism:

[MarkupExtensionReturnType(typeof(Length))]
public class LengthExtension : MarkupExtension
{
    public LengthExtension(string value)
    {
        this.Value = Length.Parse(value, CultureInfo.InvariantCulture);
    }

    public Length Value { get; private set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this.Value;
    }
}

This works but I'm not sure about if there are any downsides.

like image 43
Johan Larsson Avatar answered Sep 18 '22 15:09

Johan Larsson