title: Using an ExpandableObjectConverter on a Generic class for a PropertyGrid
body: <p>I want to have a property grid that looks like this when it has two SteppedValue objects:</p>
  
  <p><img src="https://i.stack.imgur.com/XAQpv.png" alt="enter image description here"></p>
  
  <p>But I would also like the SteppedValue object to be a generic, for example:</p>
  
  <pre><code>var fastEma = new SteppedValue&lt;int&gt;(); 
  var slowEma = new SteppedValue&lt;float&gt;();
  </code></pre>
  
  <p>I have this mostly working by implementing ExpandableObjectConverter... but the only problem I am having is when I instantiate the object to return in ConvertFrom... I can't figure how to get the System.Type of T (from the instance of the generic) at this point.</p>
  
  <p><strong>Problem Code</strong></p>
  
  <pre><code>public override object ConvertFrom(ITypeDescriptorContext iTypeDescriptorContext, CultureInfo cultureInfo, object value)
  {
      if (value is string)
      {
          var classType = typeof(SteppedValue&lt;&gt;);
          Type[] typeArgs = { typeof(int) }; // &lt;== Need to determine this 
                                             //  needs to be T of the generic
                                             //  instance (not "typeof(int)")
          var instanceType = classType.MakeGenericType(typeArgs);
          object o = Activator.CreateInstance(instanceType, value);
          return o;
      }
      return base.ConvertFrom(iTypeDescriptorContext, cultureInfo, value);
  }
  </code></pre>
  
  <p><strong>Full Code</strong></p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Globalization;
  using System.Linq;
  
  namespace Test
  {
      [TypeConverter(typeof(SteppedValueConverter))]
      public class SteppedValue&lt;T&gt;
      {
          public T Begin { get; set; }
          public T End { get; set; }
          public T Step { get; set; }
  
          public SteppedValue(T begin, T end, T step) 
          { 
              Begin = begin;
              End = end;
              Step = step;
          }
  
          public SteppedValue(string str)
          {
              var parts = ParseParts(str);
              Begin = parts[0];
              End = parts[1];
              Step = parts[2];
          }
  
          public static T ToT(object obj)
          {
              return (T)Convert.ChangeType(obj, typeof(T));
          }
  
          public static SteppedValue&lt;T&gt; Parse(string str)
          {
              return new SteppedValue&lt;T&gt;(str);
          }
  
          public List&lt;T&gt; ParseParts(string str)
          {
              while (str.Contains("  ")) str = str.Replace("  ", " ");
              var arr = str.Trim().Split(' ');
              if (arr.Length == 0)
                  return new List&lt;T&gt; { default(T), default(T), default(T) };
              else if (arr.Length == 1)
                  return new List&lt;T&gt; { ToT(arr[0]), ToT(arr[0]), default(T) };
              else if (arr.Length == 3 &amp;&amp; arr[1].ToLower() == "to")
                  return new List&lt;T&gt; { ToT(arr[0]), ToT(arr[2]), default(T) };
              else if (arr.Length == 5 &amp;&amp; arr[1].ToLower() == "to" &amp;&amp; arr[3].ToLower() == "step")
                  return new List&lt;T&gt; { ToT(arr[0]), ToT(arr[2]), ToT(arr[4]) };
              throw new Exception("Unable to parse'" + str + "'");
          }
  
          public override string ToString()
          {
              if (Begin.Equals(End))
                  return Begin.ToString();
              else if (Step == null || Step.ToString() == "")
                  return Begin + " to " + End;
              else
                  return Begin + " to " + End + " step " + Step;
          }
      }
  
      public class SteppedValueConverter : ExpandableObjectConverter
      {
          public override bool CanConvertFrom(ITypeDescriptorContext iTypeDescriptorContext, Type type)
          {
              if (type == typeof(string))
                  return true;
              return base.CanConvertFrom(iTypeDescriptorContext, type);
          }
  
          public override object ConvertFrom(ITypeDescriptorContext iTypeDescriptorContext, CultureInfo cultureInfo, object value)
          {
              if (value is string)
              {
                  var classType = typeof(SteppedValue&lt;&gt;);
                  Type[] typeArgs = { typeof(int) }; // &lt;== Need to determine this
                  var instanceType = classType.MakeGenericType(typeArgs);
                  object o = Activator.CreateInstance(instanceType, value);
  
                  return o;
              }
              return base.ConvertFrom(iTypeDescriptorContext, cultureInfo, value);
          }
  
          public override object ConvertTo(ITypeDescriptorContext iTypeDescriptorContext, CultureInfo cultureInfo, object value, Type destinationType)
          {
  
              if (destinationType == typeof(string) &amp;&amp; value.GetType().GetGenericTypeDefinition() == typeof(SteppedValue&lt;&gt;))
                  return value.ToString();
  
              return base.ConvertTo(iTypeDescriptorContext, cultureInfo, value, destinationType);
          }
      }
  }
  </code></pre>