Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I came back to this need much later, as we have some assemblies in the GAC and things like NHibernate needed to resolve them. Rather than adding all these qualifyAssembly elements to every app.config, the following code allows us to add them to our machine.config.</p> <pre><code>using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Reflection; using System.Xml; using System.Xml.XPath; namespace MyNamespace { /// &lt;summary&gt; /// Implements &lt;see cref="IDisposable"/&gt; to provide a scope for resolving /// assemblies described in the machine.config file with /// &amp;lt;qualifyAssembly&amp;gt; elements. /// &lt;/summary&gt; /// &lt;remarks&gt; /// Because the framework only respects &amp;lt;qualifyAssembly&amp;gt; at the /// application configuration level, this class provides similar /// functionality for this element at the machine configuration level. /// You can wrap a new instance of this class in a &lt;b&gt;using&lt;/b&gt; statement /// to get resolution within a specific scope; or, you can call the /// &lt;see cref="AssemblyResolver.Attach()"/&gt; method to get /// resolution for the lifetime of the current &lt;see cref="AppDomain"/&gt;. /// &lt;/remarks&gt; public sealed class AssemblyResolver : IDisposable { #region Private fields and implementation private static Dictionary&lt;string, string&gt; _qualifiedNames; private static Assembly ResolveAssembly(object sender, ResolveEventArgs args) { if(_qualifiedNames == null) { // // Lazily initialize short/long name mappings. // _qualifiedNames = BuildQualifiedNameList(); } if(!_qualifiedNames.ContainsKey(args.Name)) { return null; } try { return Assembly.Load(_qualifiedNames[args.Name]); } catch(FileNotFoundException) { // // TODO: Should this exception be propogated? // It probably should not be hidden from the consumer // since it likely indicates a configuration error. // return null; } } private static Dictionary&lt;string, string&gt; BuildQualifiedNameList() { var dict = new Dictionary&lt;string, string&gt;(StringComparer.InvariantCultureIgnoreCase); // // Get runtime XML data // var xml = GetConfigXml(GetMachineRuntimeSection()); if(xml == null) { return dict; } // // Iterate the qualifyAssembly elements and register in the list // var navigator = xml.CreateNavigator(); foreach(XPathNavigator qualifyAssembly in navigator.Select("runtime/asm:assemblyBinding/asm:qualifyAssembly", CreateNamespaceManager())) { dict.Add( qualifyAssembly.GetAttribute("partialName", string.Empty), qualifyAssembly.GetAttribute("fullName", string.Empty)); } return dict; } private static ConfigurationSection GetMachineRuntimeSection() { System.Configuration.Configuration machineConfig = ConfigurationManager.OpenMachineConfiguration(); return machineConfig.GetSection("runtime") as ConfigurationSection; } private static IXPathNavigable GetConfigXml(ConfigurationSection runtimeSection) { var ignoreSection = runtimeSection as IgnoreSection; if(ignoreSection == null) { return null; } // // Cheat via Reflection to get the XML content of the config // section. // FieldInfo field = typeof(IgnoreSection).GetField("_rawXml", BindingFlags.Instance | BindingFlags.NonPublic); string rawXml = (string)field.GetValue(ignoreSection); return new XPathDocument(new StringReader(rawXml)); } private static IXmlNamespaceResolver CreateNamespaceManager() { var nsmgr = new XmlNamespaceManager(new NameTable()); nsmgr.AddNamespace("asm", "urn:schemas-microsoft-com:asm.v1"); return nsmgr; } #endregion /// &lt;summary&gt; /// Creates a new &lt;see cref="AssemblyResolver"/&gt;. /// &lt;/summary&gt; public AssemblyResolver() { AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly); } /// &lt;summary&gt; /// Removes the current &lt;see cref="AssemblyResolver"/&gt; /// from the &lt;see cref="AppDomain"/&gt;. /// &lt;/summary&gt; public void Dispose() { AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(ResolveAssembly); GC.SuppressFinalize(this); } /// &lt;summary&gt; /// Provides qualified assembly resolution for the lifetime of the /// current &lt;see cref="AppDomain"/&gt;. /// &lt;/summary&gt; public static void Attach() { Attach(AppDomain.CurrentDomain); } /// &lt;summary&gt; /// Provides qualified assembly resolution for the lifetime of an /// &lt;see cref="AppDomain"/&gt;. /// &lt;/summary&gt; /// &lt;param name="appDomain"&gt; /// The &lt;see cref="AppDomain"/&gt; to service. /// &lt;/param&gt; public static void Attach(AppDomain appDomain) { appDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly); } } } </code></pre> <p>In most cases, we limit the scope of it, by using it like this:</p> <pre><code>using(new AssemblyResolver()) { // // NHibernate initialization or whatever // } </code></pre> <p>It can also be used in app startup code or global.asax, and persist for the lifetime of the application, like so:</p> <pre><code>AssemblyResolver.Attach(); // // or // AssemblyResolver.Attach(AppDomain.CurrentDomain); </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload