title: Create Roslyn C# analyzer that is aware of constructor argument types for class in assembly
body: <p><strong>Background:</strong></p>
  
  <p>I have an attribute that indicates that a property of field in an object <code>IsMagic</code>.  I also have a <code>Magician</code> class that runs over any object and <code>MakesMagic</code> by extracting each field and property that <code>IsMagic</code> and wraps it in a <code>Magic</code> wrapper.</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Reflection;
  
  namespace MagicTest
  {
  
      /// &lt;summary&gt;
      /// An attribute that allows us to decorate a class with information that identifies which member is magic.
      /// &lt;/summary&gt;
      [AttributeUsage(AttributeTargets.Property|AttributeTargets.Field, AllowMultiple = false)]
      class IsMagic : Attribute { }
  
      public class Magic
      {
          // Internal data storage
          readonly public dynamic value;
  
          #region My ever-growing list of constructors
          public Magic(int input) { value = input; }
          public Magic(string input) { value = input; }
          public Magic(IEnumerable&lt;bool&gt; input) { value = input; }
          // ...
          #endregion
  
          public bool CanMakeMagicFromType(Type targetType)
          {
              if (targetType == null) return false;
              ConstructorInfo publicConstructor = typeof(Magic).GetConstructor(new[] { targetType });
              if (publicConstructor != null) return true;  // We can make Magic from this input type!!!
              return false;
          }
  
          public override string ToString()
          {
              return value.ToString(); 
          }
      }
  
      public static class Magician
      {
          /// &lt;summary&gt;
          /// A method that returns the members of anObject that have been marked with an IsMagic attribute.
          /// Each member will be wrapped in Magic.
          /// &lt;/summary&gt;
          /// &lt;param name="anObject"&gt;&lt;/param&gt;
          /// &lt;returns&gt;&lt;/returns&gt;
          public static List&lt;Magic&gt; MakeMagic(object anObject)
          {
              Type type = anObject?.GetType() ?? null;
              if (type == null) return null; // Sanity check
  
              List&lt;Magic&gt; returnList = new List&lt;Magic&gt;();
  
              // Any field or property of the class that IsMagic gets added to the returnList in a Magic wrapper
              MemberInfo[] objectMembers = type.GetMembers();
              foreach (MemberInfo mi in objectMembers)
              {
                  bool isMagic = (mi.GetCustomAttributes&lt;IsMagic&gt;().Count() &gt; 0);
                  if (isMagic)
                  {
                      dynamic memberValue = null;
                      if (mi.MemberType == MemberTypes.Property) memberValue = ((PropertyInfo)mi).GetValue(anObject);
                      else if (mi.MemberType == MemberTypes.Field) memberValue = ((FieldInfo)mi).GetValue(anObject);
                      if (memberValue == null) continue;
  
                      returnList.Add(new Magic(memberValue)); // This could fail at run-time!!!
                  }
  
              }
  
              return returnList;
          }
      }
  }
  </code></pre>
  
  <p>The Magician can <code>MakeMagic</code> on <code>anObject</code> with at least one field or property that <code>IsMagic</code> to produce a generic <code>List</code> of <code>Magic</code>, like so:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  
  namespace MagicTest
  {
      class Program
      {
          class Mundane
          {
              [IsMagic] public string foo;
              [IsMagic] public int feep;
              public float zorp; // If this [IsMagic], we'll have a run-time error
          }
  
          static void Main(string[] args)
          {
              Mundane anObject = new Mundane
              {
                  foo = "this is foo",
                  feep = -10,
                  zorp = 1.3f
              };
  
              Console.WriteLine("Magic:");
              List&lt;Magic&gt; myMagics = Magician.MakeMagic(anObject);
              foreach (Magic aMagic in myMagics) Console.WriteLine("  {0}",aMagic.ToString());
              Console.WriteLine("More Magic: {0}", new Magic("this works!"));
              //Console.WriteLine("More Magic: {0}", new Magic(Mundane)); // build-time error!
  
              Console.WriteLine("\nPress Enter to continue");
              Console.ReadLine();
          }
      }
  }
  </code></pre>
  
  <p>Notice that <code>Magic</code> wrappers can only go around properties or fields of certain types.  This means that only property or field that contains data of specific types should be marked as <code>IsMagic</code>.  To make matters more complicated, I expect the list of specific types to change as business needs evolve (since programming Magic is in such high demand).</p>
  
  <p>The good news is that the <code>Magic</code> has some build time safety.  If I try to add code like <code>new Magic(true)</code> Visual Studio will tell me it's wrong, since there is no constructor for <code>Magic</code> that takes a <code>bool</code>.  There is also some run-time checking, since the <code>Magic.CanMakeMagicFromType</code> method can be used to catch problems with dynamic variables.</p>
  
  <p><strong>Problem Description:</strong></p>
  
  <p>The bad news is that there's no build-time checking on the <code>IsMagic</code> attribute.  I can happily say a <code>Dictionary&lt;string,bool&gt;</code> field in some class <code>IsMagic</code>, and I won't be told that it's a problem until run-time.  Even worse, the users of my magical code will be creating their own mundane classes and decorating their properties and fields with the <code>IsMagic</code> attribute.  I'd like to help them see problems before they become problems.</p>
  
  <p><strong>Proposed Solution:</strong></p>
  
  <p>Ideally, I could put some kind of AttributeUsage flag on my <code>IsMagic</code> attribute to tell Visual Studio to use the <code>Magic.CanMakeMagicFromType()</code> method to check the property or field type that the <code>IsMagic</code> attribute is being attached to.  Unfortunately, there doesn't seem to be such an attribute.</p>
  
  <p>However, it seems like it should be possible to use Roslyn to present an error when <code>IsMagic</code> is placed on a field or property that has a <code>Type</code> that can't be wrapped in <code>Magic</code>.</p>
  
  <p><strong>Where I need help:</strong></p>
  
  <p>I am having trouble designing the Roslyn analyser.  The heart of the problem is that <code>Magic.CanMakeMagicFromType</code> takes in <code>System.Type</code>, but Roslyn uses <code>ITypeSymbol</code> to represent object types.</p>
  
  <p>The ideal analyzer would:</p>
  
  <ol>
  <li>Not require me to keep a list of allowed types that can be wrapped in <code>Magic</code>.  After all, <code>Magic</code> has a list of constructors that serve this purpose.</li>
  <li>Allow natural casting of types.  For instance, if <code>Magic</code> has a constructor that takes in <code>IEnumerable&lt;bool&gt;</code>, then Roslyn should allow <code>IsMagic</code> to be attached to a property with type <code>List&lt;bool&gt;</code> or <code>bool[]</code>.  This casting of Magic is critical to the Magician's functionality.</li>
  </ol>
  
  <p>I'd appreciate any direction on how to code a Roslyn analyzer that is "aware" of the constructors in <code>Magic</code>.</p>