Reflect, but carefully…

Recently, I have been working on code that needs to load to a .NET assembly at runtime (for those who are curious: this is the Microsoft.Web.Administration assembly, which provides programmatic access to a lot of IIS 7 functionality). As a proof of concept, I wanted to do something simple with this assembly using reflection: print a list of sites on the IIS server.

Being relatively new to reflection, I decided to follow this pattern:

<div><span style="color: #008080;"> 1</span> <span style="color: #0000FF;">using</span><span style="color: #000000;"> System;
</span><span style="color: #008080;"> 2</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Collections.Generic;
</span><span style="color: #008080;"> 3</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Linq;
</span><span style="color: #008080;"> 4</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Text;
</span><span style="color: #008080;"> 5</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Reflection;
</span><span style="color: #008080;"> 6</span> <span style="color: #000000;">
</span><span style="color: #008080;"> 7</span> <span style="color: #000000;"></span><span style="color: #0000FF;">namespace</span><span style="color: #000000;"> ReflectionPlayground
</span><span style="color: #008080;"> 8</span> <span style="color: #000000;">{
</span><span style="color: #008080;"> 9</span> <span style="color: #000000;">    </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> Program
</span><span style="color: #008080;">10</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">11</span> <span style="color: #000000;">        </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Main(</span><span style="color: #0000FF;">string</span><span style="color: #000000;">[] args)
</span><span style="color: #008080;">12</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">13</span> <span style="color: #000000;">
</span><span style="color: #008080;">14</span> <span style="color: #000000;">            System.Reflection.Assembly mwaAssembly </span><span style="color: #000000;">=</span><span style="color: #000000;"> System.Reflection.Assembly.LoadFile(</span><span style="color: #800000;">@"</span><span style="color: #800000;">C:WindowsSystem32inetsrvMicrosoft.Web.Administration.dll</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #008080;">15</span> <span style="color: #000000;">            System.Type ServerManagerType </span><span style="color: #000000;">=</span><span style="color: #000000;"> mwaAssembly.GetType(</span><span style="color: #800000;">"</span><span style="color: #800000;">Microsoft.Web.Administration.ServerManager</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #008080;">16</span> <span style="color: #000000;">            System.Type SiteType </span><span style="color: #000000;">=</span><span style="color: #000000;"> mwaAssembly.GetType(</span><span style="color: #800000;">"</span><span style="color: #800000;">Microsoft.Web.Administration.Site</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #008080;">17</span> <span style="color: #000000;">            System.Type SiteCollectionType </span><span style="color: #000000;">=</span><span style="color: #000000;"> mwaAssembly.GetType(</span><span style="color: #800000;">"</span><span style="color: #800000;">Microsoft.Web.Administration.SiteCollection</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #008080;">18</span> <span style="color: #000000;">
</span><span style="color: #008080;">19</span> <span style="color: #000000;">            </span><span style="color: #0000FF;">object</span><span style="color: #000000;">[] argsToPass </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> </span><span style="color: #0000FF;">object</span><span style="color: #000000;">[] { };
</span><span style="color: #008080;">20</span> <span style="color: #000000;">
</span><span style="color: #008080;">21</span> <span style="color: #000000;">            </span><span style="color: #0000FF;">object</span><span style="color: #000000;"> ServerManagerObject </span><span style="color: #000000;">=</span><span style="color: #000000;"> mwaAssembly.CreateInstance(</span><span style="color: #800000;">"</span><span style="color: #800000;">Microsoft.Web.Administration.ServerManager</span><span style="color: #800000;">"</span><span style="color: #000000;">,
</span><span style="color: #008080;">22</span> <span style="color: #000000;">                                                                    </span><span style="color: #0000FF;">false</span><span style="color: #000000;">,
</span><span style="color: #008080;">23</span> <span style="color: #000000;">                                                                    BindingFlags.CreateInstance,
</span><span style="color: #008080;">24</span> <span style="color: #000000;">                                                                    </span><span style="color: #0000FF;">null</span><span style="color: #000000;">,
</span><span style="color: #008080;">25</span> <span style="color: #000000;">                                                                    argsToPass,
</span><span style="color: #008080;">26</span> <span style="color: #000000;">                                                                    </span><span style="color: #0000FF;">null</span><span style="color: #000000;">,
</span><span style="color: #008080;">27</span> <span style="color: #000000;">                                                                    </span><span style="color: #0000FF;">null</span><span style="color: #000000;">);
</span><span style="color: #008080;">28</span> <span style="color: #000000;">
</span><span style="color: #008080;">29</span> <span style="color: #000000;">            MethodInfo GetAdministrationConfigurationMethod </span><span style="color: #000000;">=</span><span style="color: #000000;"> ServerManagerType.GetMethod(</span><span style="color: #800000;">"</span><span style="color: #800000;">GetAdministrationConfiguration</span><span style="color: #800000;">"</span><span style="color: #000000;">, System.Type.EmptyTypes, </span><span style="color: #0000FF;">null</span><span style="color: #000000;">);
</span><span style="color: #008080;">30</span> <span style="color: #000000;">            </span><span style="color: #0000FF;">object</span><span style="color: #000000;"> AdministrationConfigurationObject </span><span style="color: #000000;">=</span><span style="color: #000000;"> GetAdministrationConfigurationMethod.Invoke(ServerManagerObject, </span><span style="color: #0000FF;">null</span><span style="color: #000000;">);
</span><span style="color: #008080;">31</span> <span style="color: #000000;">
</span><span style="color: #008080;">32</span> <span style="color: #000000;">            </span><span style="color: #0000FF;">object</span><span style="color: #000000;"> SitesCollection </span><span style="color: #000000;">=</span><span style="color: #000000;"> ServerManagerType.GetProperty(</span><span style="color: #800000;">"</span><span style="color: #800000;">Sites</span><span style="color: #800000;">"</span><span style="color: #000000;">).GetValue(ServerManagerObject, </span><span style="color: #0000FF;">null</span><span style="color: #000000;">);
</span><span style="color: #008080;">33</span> <span style="color: #000000;">
</span><span style="color: #008080;">34</span> <span style="color: #000000;">            IEnumerator</span><span style="color: #000000;"><</span><span style="color: #0000FF;">object</span><span style="color: #000000;">></span><span style="color: #000000;"> SitesCollectionEnumerator </span><span style="color: #000000;">=</span><span style="color: #000000;"> (IEnumerator</span><span style="color: #000000;"><</span><span style="color: #0000FF;">object</span><span style="color: #000000;">></span><span style="color: #000000;">)SiteCollectionType.GetMethod(</span><span style="color: #800000;">"</span><span style="color: #800000;">GetEnumerator</span><span style="color: #800000;">"</span><span style="color: #000000;">).Invoke(SitesCollection, </span><span style="color: #0000FF;">null</span><span style="color: #000000;">);
</span><span style="color: #008080;">35</span> <span style="color: #000000;">
</span><span style="color: #008080;">36</span> <span style="color: #000000;">            </span><span style="color: #0000FF;">while</span><span style="color: #000000;"> (SitesCollectionEnumerator.MoveNext())
</span><span style="color: #008080;">37</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">38</span> <span style="color: #000000;">                </span><span style="color: #0000FF;">object</span><span style="color: #000000;"> CurrentSite </span><span style="color: #000000;">=</span><span style="color: #000000;"> SitesCollectionEnumerator.Current;
</span><span style="color: #008080;">39</span> <span style="color: #000000;">                PropertyInfo CurrentSiteName </span><span style="color: #000000;">=</span><span style="color: #000000;"> SiteType.GetProperty(</span><span style="color: #800000;">"</span><span style="color: #800000;">Name</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #008080;">40</span> <span style="color: #000000;">                Console.WriteLine(CurrentSiteName.GetValue(CurrentSite, </span><span style="color: #0000FF;">null</span><span style="color: #000000;">));
</span><span style="color: #008080;">41</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">42</span> <span style="color: #000000;">
</span><span style="color: #008080;">43</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">44</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">45</span> <span style="color: #000000;">}
</span><span style="color: #008080;">46</span> <span style="color: #000000;"></span></div>

There are a few things immediately wrong with this approach … what should have been really simple code, now becomes bloated and difficult to read and maintain. The other problem is that because I am hard-coding method names and properties, I am not gaining a whole lot by doing reflection.

So, what’s the alternative? It turns out that there’s a good pattern for this:

1. Add a reference to the DLL in your project (e.g. MyApp.dll)

2. Create a new utility class:

<div><span style="color: #008080;"> 1</span> <span style="color: #0000FF;">using</span><span style="color: #000000;"> System;
</span><span style="color: #008080;"> 2</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Diagnostics;
</span><span style="color: #008080;"> 3</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.IO;
</span><span style="color: #008080;"> 4</span> <span style="color: #000000;">
</span><span style="color: #008080;"> 5</span> <span style="color: #000000;"></span><span style="color: #0000FF;">namespace</span><span style="color: #000000;"> MyApp.Utility
</span><span style="color: #008080;"> 6</span> <span style="color: #000000;">{
</span><span style="color: #008080;"> 7</span> <span style="color: #000000;">    </span><span style="color: #0000FF;">internal</span><span style="color: #000000;"> </span><span style="color: #0000FF;">sealed</span><span style="color: #000000;"> </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> SomeappDependency
</span><span style="color: #008080;"> 8</span> <span style="color: #000000;">    {
</span><span style="color: #008080;"> 9</span> <span style="color: #000000;">        </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">bool</span><span style="color: #000000;"> _dependencyAvailable;
</span><span style="color: #008080;">10</span> <span style="color: #000000;">        </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">bool</span><span style="color: #000000;"> _checked;
</span><span style="color: #008080;">11</span> <span style="color: #000000;">
</span><span style="color: #008080;">12</span> <span style="color: #000000;">        </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> Type GetTypeFromDependency()
</span><span style="color: #008080;">13</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">14</span> <span style="color: #000000;">            Type type </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">typeof</span><span style="color: #000000;">(MyApp.Someclass);
</span><span style="color: #008080;">15</span> <span style="color: #000000;">            </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> type;
</span><span style="color: #008080;">16</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">17</span> <span style="color: #000000;">
</span><span style="color: #008080;">18</span> <span style="color: #000000;">        </span><span style="color: #0000FF;">internal</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">bool</span><span style="color: #000000;"> IsAvailable()
</span><span style="color: #008080;">19</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">20</span> <span style="color: #000000;">            </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (_checked)
</span><span style="color: #008080;">21</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">22</span> <span style="color: #000000;">                </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> _dependencyAvailable;
</span><span style="color: #008080;">23</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">24</span> <span style="color: #000000;">            </span><span style="color: #0000FF;">else</span><span style="color: #000000;">
</span><span style="color: #008080;">25</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">26</span> <span style="color: #000000;">                </span><span style="color: #0000FF;">try</span><span style="color: #000000;">
</span><span style="color: #008080;">27</span> <span style="color: #000000;">                {
</span><span style="color: #008080;">28</span> <span style="color: #000000;">                    GetTypeFromDependency();
</span><span style="color: #008080;">29</span> <span style="color: #000000;">                    _dependencyAvailable </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">true</span><span style="color: #000000;">;
</span><span style="color: #008080;">30</span> <span style="color: #000000;">                }
</span><span style="color: #008080;">31</span> <span style="color: #000000;">                </span><span style="color: #0000FF;">catch</span><span style="color: #000000;"> (FileNotFoundException)
</span><span style="color: #008080;">32</span> <span style="color: #000000;">                {
</span><span style="color: #008080;">33</span> <span style="color: #000000;">                    _dependencyAvailable </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">false</span><span style="color: #000000;">;
</span><span style="color: #008080;">34</span> <span style="color: #000000;">                }
</span><span style="color: #008080;">35</span> <span style="color: #000000;">
</span><span style="color: #008080;">36</span> <span style="color: #000000;">                _checked </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">true</span><span style="color: #000000;">;
</span><span style="color: #008080;">37</span> <span style="color: #000000;">                </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> _dependencyAvailable;
</span><span style="color: #008080;">38</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">39</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">40</span> <span style="color: #000000;">
</span><span style="color: #008080;">41</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">42</span> <span style="color: #000000;">}
</span><span style="color: #008080;">43</span> <span style="color: #000000;"></span></div>
  1. From your main code, write an if-else block:

    1 if (SomeappDependency.IsAvailable()) 2 { 3 // call code in the DLL 4 } 5 else 6 { 7 // log an error 8 }

How does this work? The key lies in the fact that .NET loads dependencies in a just-in-time (JIT) manner. In this case, it’s only when the GetTypeFromDependency() method is called that the MyApp DLL is loaded.

Important note: the first call into the MyApp DLL needs to be in a separate method because the method will throw when it’s first JIT’ed.

Some benefits of this approach: we get Intellisense, and our code becomes a LOT shorter:

<div><span style="color: #008080;"> 1</span> <span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Text;
</span><span style="color: #008080;"> 2</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System;
</span><span style="color: #008080;"> 3</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Collections.Generic;
</span><span style="color: #008080;"> 4</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Xml;
</span><span style="color: #008080;"> 5</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Xml.XPath;
</span><span style="color: #008080;"> 6</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> Microsoft.Web.Administration;
</span><span style="color: #008080;"> 7</span> <span style="color: #000000;"></span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Configuration;
</span><span style="color: #008080;"> 8</span> <span style="color: #000000;">
</span><span style="color: #008080;"> 9</span> <span style="color: #000000;"></span><span style="color: #0000FF;">namespace</span><span style="color: #000000;"> MWATest
</span><span style="color: #008080;">10</span> <span style="color: #000000;">{
</span><span style="color: #008080;">11</span> <span style="color: #000000;">    </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> Program
</span><span style="color: #008080;">12</span> <span style="color: #000000;">    {
</span><span style="color: #008080;">13</span> <span style="color: #000000;">        </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Main(</span><span style="color: #0000FF;">string</span><span style="color: #000000;">[] args)
</span><span style="color: #008080;">14</span> <span style="color: #000000;">        {
</span><span style="color: #008080;">15</span> <span style="color: #000000;">            </span><span style="color: #0000FF;">using</span><span style="color: #000000;"> (ServerManager serverManager </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> ServerManager())
</span><span style="color: #008080;">16</span> <span style="color: #000000;">            {
</span><span style="color: #008080;">17</span> <span style="color: #000000;">                SiteCollection siteCollection </span><span style="color: #000000;">=</span><span style="color: #000000;"> serverManager.Sites;
</span><span style="color: #008080;">18</span> <span style="color: #000000;">                </span><span style="color: #0000FF;">foreach</span><span style="color: #000000;">(Site site </span><span style="color: #0000FF;">in</span><span style="color: #000000;"> siteCollection){
</span><span style="color: #008080;">19</span> <span style="color: #000000;">                    Console.WriteLine(site.Name);
</span><span style="color: #008080;">20</span> <span style="color: #000000;">                }
</span><span style="color: #008080;">21</span> <span style="color: #000000;">            }
</span><span style="color: #008080;">22</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">23</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">24</span> <span style="color: #000000;">}
</span><span style="color: #008080;">25</span> <span style="color: #000000;"></span></div>