title: Control with custom TypeConverter does not work after project rebuild
body: <h2>Overview</h2>
  
  <p>I have a C# project <code>ControlsLib</code> which contains the following (code to follow later):</p>
  
  <ol>
  <li>A custom C# control <code>Control_Audible</code> that plays a .wav file that is selected at design-time from the properties pane</li>
  <li>A <code>SoundItem</code> class as the class to support which file will be played</li>
  <li>A <code>SoundItemConverter</code> class as a <code>TypeConverter</code> for elegantly selecting which audio file to play in the properties window.</li>
  </ol>
  
  <h2>What IS working</h2>
  
  <p>My code works as expected when my solution is FIRST opened and my <code>ControlsLib</code> project is NOT built.</p>
  
  <p>When I add <code>Control_Audible</code> to a form, I can select an audio file from the available audio resources:</p>
  
  <p><a href="https://i.stack.imgur.com/TT9oR.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/TT9oR.png" alt="Select audio file from available audio resources; &quot;None&quot; is NOT bold..."></a></p>
  
  <p>And the designer file generates code as I would expect when the non-default SoundItem is selected:</p>
  
  <p><a href="https://i.stack.imgur.com/rSnet.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/rSnet.png" alt="Expected designer code generated from non-default SoundItem"></a></p>
  
  <h2>What is NOT working</h2>
  
  <p>My code seems to NOT work as expected after building/rebuilding my <code>ControlsLib</code> project and add my <code>Control_Audible</code> control to a form...</p>
  
  <p>The available audio resource files are populated in the dropdown as expected, but the SoundItem specified as the <code>DefaultValue</code> ("None") is <strong>Bold</strong> when it really should not be:</p>
  
  <p><a href="https://i.stack.imgur.com/lgpJg.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/lgpJg.png" alt="Select audio file from available audio resources; DefaultValue &quot;None&quot; is BOLD!?"></a></p>
  
  <p>Also, whenever I try to save the form, I receive the following error:</p>
  
  <p><a href="https://i.stack.imgur.com/0PJxD.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/0PJxD.png" alt="Code generation ... failed ... Unable to convert ... to InstanceDescriptor"></a></p>
  
  <p>I was at one time able to generate some auto-code for my <code>Control_Audible</code>, but even then it did not generate the code I expected, and now it seems to not generate any code at all and my <code>ConvertTo</code> function is messed up.</p>
  
  <h2>Question</h2>
  
  <p>It seems to work fine if I don't build my <code>ControlsLib</code> project, but I can't expect to have to restart Visual Studio every time I want this thing to work.  I should be able to rebuild my project as much as desired and still have my control work properly.  I will mention I am using <strong>Visual Studio 2015</strong>.</p>
  
  <p>Does anyone have any ideas why this is behaving this way?  I've spent quite a bit of time on this and cannot figure out why this is happening!</p>
  
  <h2>The Code</h2>
  
  <p><strong>Control_Audible.cs</strong></p>
  
  <pre><code>using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.ComponentModel.Design.Serialization;
  using System.Drawing;
  using System.Globalization;
  using System.Media;
  using System.Reflection;
  using System.Resources;
  using System.Windows.Forms;
  
  namespace ControlsLib
  {
     public class Control_Audible : UserControl
     {
        public Control_Audible() : base()
        {
           FileToPlay = SoundItem.None;
           InitializeComponent();
        }
  
        private void InitializeComponent()
        {
           this.SuspendLayout();
           // 
           // Control_Audible
           // 
           this.AutoScaleDimensions = new SizeF(6F, 13F);
           this.Name = "Control_Audible";
           this.ResumeLayout(false);
        }
  
        [Category("Sounds")]
        [DisplayName("SoundToPlay")]
        [Description("File to play")]
        [DefaultValue(typeof(SoundItem), "None")]
        //[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public SoundItem FileToPlay
        {
           get;
           set;
        }
     }
  
     [TypeConverter(typeof(SoundItemConverter))]
     [Serializable]
     public struct SoundItem
     {
        public static readonly SoundItem None = new SoundItem("None");
  
        //[Browsable(false)]
        //[DefaultValue("None")]
        //[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        internal string Name
        {
           get;
           set;
        }
  
        // Todo: Create a valid flag
        public SoundItem(string Name) : this()
        {
           this.Name = Name;
        }
  
        public SoundPlayer GetSoundPlayer()
        {
           SoundPlayer retVal = null;
  
           if (!string.IsNullOrEmpty(Name))
           {
              retVal = new SoundPlayer(AudibleSounds.ResourceManager.GetStream(Name));
           }
  
           return retVal;
        }
  
        public override string ToString()
        {
           return Name;
        }
  
        public static bool operator ==(SoundItem left, SoundItem right)
        {
           return left.Name == right.Name;
        }
  
        public static bool operator !=(SoundItem left, SoundItem right)
        {
           return !(left == right);
        }
  
        public override bool Equals(object obj)
        {
           // override Equals and write code to actually
           // test for equality so that the SoundItem created
           // from the call to ConvertFrom will be equal to
           // the field you created
  
           if (!(obj is SoundItem))
           {
              return false;
           }
  
           SoundItem comp = (SoundItem)obj;
  
           // Note value types can't have derived classes, so we don't need 
           // to check the types of the objects here.  -- Microsoft, 2/21/2001
           return comp.Name == Name;
        }
  
        public override int GetHashCode()
        {
           return Name.GetHashCode();
        }
     }
  
     public class SoundItemConverter : TypeConverter
     {
        private Dictionary&lt;string, object&gt; _resourceValues = new Dictionary&lt;string, object&gt;()
        {
           {"None", SoundItem.None },
        };
  
        public SoundItemConverter()
        {
           // Initializes the standard values list with defaults.
           ResourceSet _resourceSet = AudibleSounds.ResourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, true);
  
           if (_resourceSet == null)
           {
              throw new Exception("Missing Resource Audio files");
           }
  
           // Make a dictionary now for easier use
           foreach (DictionaryEntry entry in _resourceSet)
           {
              string resourceKey = entry.Key.ToString();
              //object resource = entry.Value;
              _resourceValues.Add(resourceKey,
                                  new SoundItem(resourceKey));
           }
        }
  
        // Indicates this converter provides a list of standard values.
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
           return true;
        }
  
        // Returns a StandardValuesCollection of standard value objects.
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
           return new StandardValuesCollection( _resourceValues.Values);
        }
  
        // Returns true for a sourceType of string to indicate that 
        // conversions from string are supported. (The 
        // GetStandardValues method requires a string to native type 
        // conversion because the items in the drop-down list are 
        // translated to string.)
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
           if (sourceType == typeof(string))
           {
              return true;
           }
  
           return base.CanConvertFrom(context, sourceType);
        }
  
        // If the type of the value to convert is string, parses the string 
        // to set the value of the property to.
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
           // This is the method that is called when you specify a default value for your type.
           // Convert a string representation to SoundItem.
           string strValue = value as string;
  
           if (strValue != null)
           {
              string text = strValue.Trim();
  
              if (text.Length == 0)
              {
                 return SoundItem.None;
              }
              else
              {
                 return new SoundItem(text);
              }
           }
  
           return base.ConvertFrom(context, culture, value);
        }
  
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destType)
        {
           if (destType == typeof(InstanceDescriptor))
           {
              return true;
           }
  
           return base.CanConvertTo(context, destType);
        }
  
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType)
        {
           if (destType == null)
           {
              throw new ArgumentNullException("destinationType");
           }
  
           if (value is SoundItem)
           {
              SoundItem si = (SoundItem)value;
  
              if (destType == typeof(string))
              {
                 TypeConverter stringConverter = TypeDescriptor.GetConverter(typeof(string));
  
                 // Note: ConvertToString will raise exception if value cannot be converted.
                 return stringConverter.ConvertToString(context, culture, si.Name);
              }
              else if (destType == typeof(InstanceDescriptor))
              {
                 ConstructorInfo ctor = typeof(SoundItem).GetConstructor(new Type[] { typeof(string) });
  
                 if (ctor != null)
                 {
                    return new InstanceDescriptor(ctor, new object[] { si.Name });
                 }
              }
           }
  
           return base.ConvertTo(context, culture, value, destType);
        }
  
        //
        // Summary:
        //     Creates an instance of this type given a set of property values for the object.
        //
        // Parameters:
        //   context:
        //     A type descriptor through which additional context can be provided.
        //
        //   propertyValues:
        //     A dictionary of new property values. The dictionary contains a series of name-value
        //     pairs, one for each property returned from SoundItemConverter.GetProperties(System.ComponentModel.ITypeDescriptorContext,System.Object,System.Attribute[]).
        //
        // Returns:
        //     The newly created object, or null if the object could not be created. The default
        //     implementation returns null.
        public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
        {
           if (propertyValues == null)
           {
              throw new ArgumentNullException("propertyValues");
           }
  
           object name = propertyValues["Name"];
  
           if (name == null || !(name is string))
           {
              throw new ArgumentException();
           }
  
           return new SoundItem((string)name);
        }
  
        //
        // Summary:
        //     Determines if changing a value on this object should require a call to SoundItemConverter.CreateInstance(System.ComponentModel.ITypeDescriptorContext,System.Collections.IDictionary)
        //     to create a new value.
        //
        // Parameters:
        //   context:
        //     A System.ComponentModel.TypeDescriptor through which additional context can be
        //     provided.
        //
        // Returns:
        //     true if the SoundItemConverter.CreateInstance(System.ComponentModel.ITypeDescriptorContext,System.Collections.IDictionary)
        //     method should be called when a change is made to one or more properties of this
        //     object; otherwise, false.
        public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
        {
           return true;
        }
  
        //
        // Summary:
        //     Retrieves the set of properties for this type. By default, a type does not return
        //     any properties.
        //
        // Parameters:
        //   context:
        //     A type descriptor through which additional context can be provided.
        //
        //   value:
        //     The value of the object to get the properties for.
        //
        //   attributes:
        //     An array of System.Attribute objects that describe the properties.
        //
        // Returns:
        //     The set of properties that are exposed for this data type. If no properties are
        //     exposed, this method might return null. The default implementation always returns
        //     null.
        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
        {
           PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(SoundItem), attributes);
           return props.Sort(new string[] { "Name" });
        }
  
        //
        // Summary:
        //     Determines if this object supports properties. By default, this is false.
        //
        // Parameters:
        //   context:
        //     A System.ComponentModel.TypeDescriptor through which additional context can be
        //     provided.
        //
        // Returns:
        //     true if SoundItemCoverter.GetProperties(System.ComponentModel.ITypeDescriptorContext,System.Object,System.Attribute[])
        //     should be called to find the properties of this object; otherwise, false.
        public override bool GetPropertiesSupported(ITypeDescriptorContext context)
        {
           return true;
        }
     }
  }
  </code></pre>
  
  <p><strong>AudibleSounds.Designer.cs</strong></p>
  
  <pre><code>//------------------------------------------------------------------------------
  // &lt;auto-generated&gt;
  //     This code was generated by a tool.
  //     Runtime Version:4.0.30319.42000
  //
  //     Changes to this file may cause incorrect behavior and will be lost if
  //     the code is regenerated.
  // &lt;/auto-generated&gt;
  //------------------------------------------------------------------------------
  
  namespace ControlsLib {
      using System;
  
  
      /// &lt;summary&gt;
      ///   A strongly-typed resource class, for looking up localized strings, etc.
      /// &lt;/summary&gt;
      // This class was auto-generated by the StronglyTypedResourceBuilder
      // class via a tool like ResGen or Visual Studio.
      // To add or remove a member, edit your .ResX file then rerun ResGen
      // with the /str option, or rebuild your VS project.
      [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
      public class AudibleSounds {
  
          private static global::System.Resources.ResourceManager resourceMan;
  
          private static global::System.Globalization.CultureInfo resourceCulture;
  
          [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
          internal AudibleSounds() {
          }
  
          /// &lt;summary&gt;
          ///   Returns the cached ResourceManager instance used by this class.
          /// &lt;/summary&gt;
          [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
          public static global::System.Resources.ResourceManager ResourceManager {
              get {
                  if (object.ReferenceEquals(resourceMan, null)) {
                      global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ControlsLib.AudibleSounds", typeof(AudibleSounds).Assembly);
                      resourceMan = temp;
                  }
                  return resourceMan;
              }
          }
  
          /// &lt;summary&gt;
          ///   Overrides the current thread's CurrentUICulture property for all
          ///   resource lookups using this strongly typed resource class.
          /// &lt;/summary&gt;
          [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
          public static global::System.Globalization.CultureInfo Culture {
              get {
                  return resourceCulture;
              }
              set {
                  resourceCulture = value;
              }
          }
  
          /// &lt;summary&gt;
          ///   Looks up a localized resource of type System.IO.UnmanagedMemoryStream similar to System.IO.MemoryStream.
          /// &lt;/summary&gt;
          public static System.IO.UnmanagedMemoryStream Horn {
              get {
                  return ResourceManager.GetStream("Horn", resourceCulture);
              }
          }
  
          /// &lt;summary&gt;
          ///   Looks up a localized resource of type System.IO.UnmanagedMemoryStream similar to System.IO.MemoryStream.
          /// &lt;/summary&gt;
          public static System.IO.UnmanagedMemoryStream HornOff {
              get {
                  return ResourceManager.GetStream("HornOff", resourceCulture);
              }
          }
      }
  }
  </code></pre>
  
  <p><strong>AudibleSounds.resx</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;root&gt;
    &lt;!-- 
      Microsoft ResX Schema 
  
      Version 2.0
  
      The primary goals of this format is to allow a simple XML format 
      that is mostly human readable. The generation and parsing of the 
      various data types are done through the TypeConverter classes 
      associated with the data types.
  
      Example:
  
      ... ado.net/XML headers &amp; schema ...
      &lt;resheader name="resmimetype"&gt;text/microsoft-resx&lt;/resheader&gt;
      &lt;resheader name="version"&gt;2.0&lt;/resheader&gt;
      &lt;resheader name="reader"&gt;System.Resources.ResXResourceReader, System.Windows.Forms, ...&lt;/resheader&gt;
      &lt;resheader name="writer"&gt;System.Resources.ResXResourceWriter, System.Windows.Forms, ...&lt;/resheader&gt;
      &lt;data name="Name1"&gt;&lt;value&gt;this is my long string&lt;/value&gt;&lt;comment&gt;this is a comment&lt;/comment&gt;&lt;/data&gt;
      &lt;data name="Color1" type="System.Drawing.Color, System.Drawing"&gt;Blue&lt;/data&gt;
      &lt;data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"&gt;
          &lt;value&gt;[base64 mime encoded serialized .NET Framework object]&lt;/value&gt;
      &lt;/data&gt;
      &lt;data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"&gt;
          &lt;value&gt;[base64 mime encoded string representing a byte array form of the .NET Framework object]&lt;/value&gt;
          &lt;comment&gt;This is a comment&lt;/comment&gt;
      &lt;/data&gt;
  
      There are any number of "resheader" rows that contain simple 
      name/value pairs.
  
      Each data row contains a name, and value. The row also contains a 
      type or mimetype. Type corresponds to a .NET class that support 
      text/value conversion through the TypeConverter architecture. 
      Classes that don't support this are serialized and stored with the 
      mimetype set.
  
      The mimetype is used for serialized objects, and tells the 
      ResXResourceReader how to depersist the object. This is currently not 
      extensible. For a given mimetype the value must be set accordingly:
  
      Note - application/x-microsoft.net.object.binary.base64 is the format 
      that the ResXResourceWriter will generate, however the reader can 
      read any of the formats listed below.
  
      mimetype: application/x-microsoft.net.object.binary.base64
      value   : The object must be serialized with 
              : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
              : and then encoded with base64 encoding.
  
      mimetype: application/x-microsoft.net.object.soap.base64
      value   : The object must be serialized with 
              : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
              : and then encoded with base64 encoding.
  
      mimetype: application/x-microsoft.net.object.bytearray.base64
      value   : The object must be serialized into a byte array 
              : using a System.ComponentModel.TypeConverter
              : and then encoded with base64 encoding.
      --&gt;
    &lt;xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"&gt;
      &lt;xsd:import namespace="http://www.w3.org/XML/1998/namespace" /&gt;
      &lt;xsd:element name="root" msdata:IsDataSet="true"&gt;
        &lt;xsd:complexType&gt;
          &lt;xsd:choice maxOccurs="unbounded"&gt;
            &lt;xsd:element name="metadata"&gt;
              &lt;xsd:complexType&gt;
                &lt;xsd:sequence&gt;
                  &lt;xsd:element name="value" type="xsd:string" minOccurs="0" /&gt;
                &lt;/xsd:sequence&gt;
                &lt;xsd:attribute name="name" use="required" type="xsd:string" /&gt;
                &lt;xsd:attribute name="type" type="xsd:string" /&gt;
                &lt;xsd:attribute name="mimetype" type="xsd:string" /&gt;
                &lt;xsd:attribute ref="xml:space" /&gt;
              &lt;/xsd:complexType&gt;
            &lt;/xsd:element&gt;
            &lt;xsd:element name="assembly"&gt;
              &lt;xsd:complexType&gt;
                &lt;xsd:attribute name="alias" type="xsd:string" /&gt;
                &lt;xsd:attribute name="name" type="xsd:string" /&gt;
              &lt;/xsd:complexType&gt;
            &lt;/xsd:element&gt;
            &lt;xsd:element name="data"&gt;
              &lt;xsd:complexType&gt;
                &lt;xsd:sequence&gt;
                  &lt;xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /&gt;
                  &lt;xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /&gt;
                &lt;/xsd:sequence&gt;
                &lt;xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /&gt;
                &lt;xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /&gt;
                &lt;xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /&gt;
                &lt;xsd:attribute ref="xml:space" /&gt;
              &lt;/xsd:complexType&gt;
            &lt;/xsd:element&gt;
            &lt;xsd:element name="resheader"&gt;
              &lt;xsd:complexType&gt;
                &lt;xsd:sequence&gt;
                  &lt;xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /&gt;
                &lt;/xsd:sequence&gt;
                &lt;xsd:attribute name="name" type="xsd:string" use="required" /&gt;
              &lt;/xsd:complexType&gt;
            &lt;/xsd:element&gt;
          &lt;/xsd:choice&gt;
        &lt;/xsd:complexType&gt;
      &lt;/xsd:element&gt;
    &lt;/xsd:schema&gt;
    &lt;resheader name="resmimetype"&gt;
      &lt;value&gt;text/microsoft-resx&lt;/value&gt;
    &lt;/resheader&gt;
    &lt;resheader name="version"&gt;
      &lt;value&gt;2.0&lt;/value&gt;
    &lt;/resheader&gt;
    &lt;resheader name="reader"&gt;
      &lt;value&gt;System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/value&gt;
    &lt;/resheader&gt;
    &lt;resheader name="writer"&gt;
      &lt;value&gt;System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/value&gt;
    &lt;/resheader&gt;
    &lt;assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /&gt;
    &lt;data name="HornOff" type="System.Resources.ResXFileRef, System.Windows.Forms"&gt;
      &lt;value&gt;Resources\HornOff.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/value&gt;
    &lt;/data&gt;
    &lt;data name="Horn" type="System.Resources.ResXFileRef, System.Windows.Forms"&gt;
      &lt;value&gt;Resources\Horn.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/value&gt;
    &lt;/data&gt;
  &lt;/root&gt;
  </code></pre>
  
  <h1>Edits</h1>
  
  <h2>Edit #1</h2>
  
  <p>I should also mention my code works as expected when the solution is debugged by running Visual Studio as an external program as so:</p>
  
  <p><a href="https://i.stack.imgur.com/OvaGG.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/OvaGG.png" alt="Control works as expected when debugging with external Visual Studio"></a></p>
  
  <p>But the code does NOT work after building my <code>ControlsLib</code> project and I add my <code>Control_Audible</code> control to a form WITHOUT debugging via an external Visual Studio (as most normal users would...).</p>