Nick Gilbert
Nick Gilbert

Reputation: 4240

Dependency Injection with TypeConverters

I have an application I'm designing which references a library that I'm also designing. Specifically, the application needs to make instances of my Sheathing class which is defined in my lower level library.

[TypeConverter(typeof(SheathingOptionsConverter))]
public class Sheathing : Lumber
{
    public string Description { get; set; }

    public Sheathing(string passedDescription)
    {
        Description = passedDescription;
    }
}

My application lists different sheathing options in a properties grid. Because it lists them in a drop down menu I had to extend the ExpandableObjectConverter twice. The first level down is my SheathingObjectConverter which properly displays a single Sheathing object

public class SheathingObjectConverter : ExpandableObjectConverter
{
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if (destinationType == typeof(Sheathing))
        {
            return true;
        }
        return base.CanConvertTo(context, destinationType);
    }

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

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, System.Type destinationType)
    {
        if (destinationType == typeof(System.String) && value is Sheathing)
        {
            Sheathing s = (Sheathing)value;
            return "Description: " + s.Description;
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string)
        {
            try
            {
                string description = (string)value;
                Sheathing s = new Sheathing(description);
                return s;
            }
            catch
            {
                throw new ArgumentException("Can not convert '" + (string)value + "' to type Sheathing");
            }
        }
        return base.ConvertFrom(context, culture, value);
    }
}

And the second level down extends SheathingObjectConverter to display a list of Sheathing objects as a drop-down menu in a property grid

public class SheathingOptionsConverter : SheathingObjectConverter
{
    /// <summary>
    /// Override the GetStandardValuesSupported method and return true to indicate that this object supports a standard set of values that can be picked from a list
    /// </summary>
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    /// <summary>
    /// Override the GetStandardValues method and return a StandardValuesCollection filled with your standard values
    /// </summary>
    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        List<Sheathing> sheathingDescriptions = SettingsController.AvailableSheathings; //ToDo: Fix needing a list from the application (higher level)
        return new StandardValuesCollection(sheathingDescriptions.ToArray());
    }
}

Here lies the problem; all the code above is in my lower level library but SettingsController is a class in my higher level application because thats where the list of sheathings is defined. Normally this problem could be solved with dependency injection but because this deals with typeconverters I am not sure if it is possible to use dependency injection. I'm not sure how to fix this issue

Upvotes: 11

Views: 1215

Answers (1)

dss539
dss539

Reputation: 6950

The context argument is the intended injection point.

Create a class like this:

class SheathingContext : ITypeDescriptorContext
{
    public List<Sheathing> AvailableSheathings 
    {
        get { return SettingsController.AvailableSheathings; }
    }
}

Then pass it as the context to the type converter. In the type converter, you can use ((SheathingContext)context).AvailableSheathings for your list.

Upvotes: 1

Related Questions