Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 563
Nick Gilbert Avatar asked Jul 08 '15 19:07

Nick Gilbert


People also ask

What is Dependency Injection (DI)?

.NET supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies. Dependency injection in .NET is a first-class citizen, along with configuration, logging, and the options pattern. A dependency is an object that another object depends on.

What is inversion of control and dependency injection?

Inversion of Control (IoC): a design pattern that stipulates frameworks should call userland code, instead of userland code calling library code Dependency injection (DI): a variant of IoC in which objects receive other objects as dependencies instead of constructors or setters

How does an injector class injects dependencies?

The injector class injects dependencies broadly in three ways: through a constructor, through a property, or through a method. Constructor Injection: In the constructor injection, the injector supplies the service (dependency) through the client class constructor.

What are the types of dependency injection?

Dependency Injection pattern involves 3 types of classes. Client Class: The client class (dependent class) is a class which depends on the service class. Service Class: The service class (dependency) is a class that provides service to the client class. Injector Class: The injector class injects service class object into the client class.


1 Answers

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.

like image 179
dss539 Avatar answered Oct 23 '22 03:10

dss539