/// <summary> /// Load assembly binding redirects from a configuration file. /// </summary> /// <param name="configFile">The configuration filename</param> /// <returns>A collection containing the assembly binding redirects</returns> public static Collection <BindingRedirectSettings> FromConfigFile( string configFile) { XmlNamespaceManager nsm; XmlDocument config; XPathNavigator navConfig; Collection <BindingRedirectSettings> redirects = new Collection <BindingRedirectSettings>(); config = new XmlDocument(); config.Load(configFile); nsm = new XmlNamespaceManager(config.NameTable); nsm.AddNamespace("binding", "urn:schemas-microsoft-com:asm.v1"); navConfig = config.CreateNavigator(); foreach (XPathNavigator nav in navConfig.Select("configuration/" + "runtime/binding:assemblyBinding/binding:dependentAssembly", nsm)) { redirects.Add(BindingRedirectSettings.FromXPathNavigator( nav, nsm, "binding")); } return(redirects); }
//===================================================================== /// <summary> /// Constructor /// </summary> /// <param name="configuration">The configuration navigator</param> public BindingRedirectResolver(XPathNavigator configuration) : base(configuration) { Collection <BindingRedirectSettings> importedSettings; BindingRedirectSettings brs; Type type; System.Reflection.FieldInfo field; Assembly asm = Assembly.GetExecutingAssembly(); FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(asm.Location); // Log the use of the resolver in case it crashes ConsoleApplication.WriteMessage(LogLevel.Info, String.Format( CultureInfo.InvariantCulture, "\r\n[{0}, version {1}]\r\n" + "Binding Redirect Assembly Resolver Component.\r\n{2}\r\n" + "http://SHFB.CodePlex.com", fvi.ProductName, fvi.ProductVersion, fvi.LegalCopyright)); // Unfortunately, the base class doesn't expose its cache so we // have to use Reflection to get at it. type = this.GetType().BaseType; field = type.GetField("cache", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); cache = (Dictionary <string, AssemblyNode>)field.GetValue(this); // Load assembly binding redirects redirects = new Collection <BindingRedirectSettings>(); foreach (XPathNavigator nav in configuration.Select( "assemblyBinding/dependentAssembly")) { brs = BindingRedirectSettings.FromXPathNavigator(nav, null, null); // Import settings from a configuration file? if (!String.IsNullOrEmpty(brs.ConfigurationFile)) { importedSettings = BindingRedirectSettings.FromConfigFile( brs.ConfigurationFile); foreach (BindingRedirectSettings imported in importedSettings) { ConsoleApplication.WriteMessage(LogLevel.Info, imported.ToString()); redirects.Add(imported); } } else { ConsoleApplication.WriteMessage(LogLevel.Info, brs.ToString()); redirects.Add(brs); } } }
//===================================================================== /// <summary> /// Create a binding redirect settings instance from an XPath navigator /// containing the settings. /// </summary> /// <param name="navigator">The XPath navigator from which to /// obtain the settings.</param> /// <param name="resolver">An optional namespace resolver. Pass null /// if one is not needed.</param> /// <param name="namespacePrefix">The namespace to prefix the elements /// with if needed. This is ignored if <c>resolver</c> is null.</param> /// <returns>A <see cref="BindingRedirectSettings"/> object containing /// the settings from the XPath navigator.</returns> /// <remarks>It should contain an element called <c>dependentAssembly</c> /// with a configFile attribute or a nested <c>assemblyIdentity</c> and /// <c>bindingRedirect</c> element that define the settings.</remarks> public static BindingRedirectSettings FromXPathNavigator( XPathNavigator navigator, IXmlNamespaceResolver resolver, string namespacePrefix) { BindingRedirectSettings brs = new BindingRedirectSettings(); XPathNavigator nav; string value; string[] versions; Version tempVersion; if (navigator != null) { value = navigator.GetAttribute("importFrom", String.Empty).Trim(); if (value.Length != 0) { brs.ConfigurationFile = value; } else { if (resolver != null) { if (!String.IsNullOrEmpty(namespacePrefix)) { namespacePrefix += ":"; } else { namespacePrefix = String.Empty; } } else { namespacePrefix = String.Empty; } nav = navigator.SelectSingleNode(namespacePrefix + "assemblyIdentity", resolver); if (nav != null) { brs.AssemblyName = nav.GetAttribute("name", String.Empty).Trim(); brs.PublicKeyToken = nav.GetAttribute("publicKeyToken", String.Empty).Trim(); brs.Culture = nav.GetAttribute("culture", String.Empty).Trim(); } nav = navigator.SelectSingleNode(namespacePrefix + "bindingRedirect", resolver); if (nav != null) { value = nav.GetAttribute("newVersion", String.Empty).Trim(); if (value.Length != 0) { brs.NewVersion = new Version(value); } value = nav.GetAttribute("oldVersion", String.Empty).Trim(); versions = value.Split('-'); if (versions.Length == 2) { if (versions[0].Trim().Length != 0) { brs.OldVersion = new Version(versions[0]); } if (versions[1].Trim().Length != 0) { brs.OldVersionTo = new Version(versions[1]); } if (brs.OldVersion > brs.oldVersionTo) { tempVersion = brs.OldVersion; brs.OldVersion = brs.oldVersionTo; brs.oldVersionTo = tempVersion; } } else { brs.OldVersion = new Version(versions[0]); } } } } return(brs); }
//===================================================================== /// <summary> /// Create a binding redirect settings instance from an XPath navigator /// containing the settings. /// </summary> /// <param name="navigator">The XPath navigator from which to /// obtain the settings.</param> /// <param name="resolver">An optional namespace resolver. Pass null /// if one is not needed.</param> /// <param name="namespacePrefix">The namespace to prefix the elements /// with if needed. This is ignored if <c>resolver</c> is null.</param> /// <returns>A <see cref="BindingRedirectSettings"/> object containing /// the settings from the XPath navigator.</returns> /// <remarks>It should contain an element called <c>dependentAssembly</c> /// with a configFile attribute or a nested <c>assemblyIdentity</c> and /// <c>bindingRedirect</c> element that define the settings.</remarks> public static BindingRedirectSettings FromXPathNavigator( XPathNavigator navigator, IXmlNamespaceResolver resolver, string namespacePrefix) { BindingRedirectSettings brs = new BindingRedirectSettings(); XPathNavigator nav; string value; string[] versions; Version tempVersion; if(navigator != null) { value = navigator.GetAttribute("importFrom", String.Empty).Trim(); if(value.Length != 0) brs.ConfigurationFile = value; else { if(resolver != null) { if(!String.IsNullOrEmpty(namespacePrefix)) namespacePrefix += ":"; else namespacePrefix = String.Empty; } else namespacePrefix = String.Empty; nav = navigator.SelectSingleNode(namespacePrefix + "assemblyIdentity", resolver); if(nav != null) { brs.AssemblyName = nav.GetAttribute("name", String.Empty).Trim(); brs.PublicKeyToken = nav.GetAttribute("publicKeyToken", String.Empty).Trim(); brs.Culture = nav.GetAttribute("culture", String.Empty).Trim(); } nav = navigator.SelectSingleNode(namespacePrefix + "bindingRedirect", resolver); if(nav != null) { value = nav.GetAttribute("newVersion", String.Empty).Trim(); if(value.Length != 0) brs.NewVersion = new Version(value); value = nav.GetAttribute("oldVersion", String.Empty).Trim(); versions = value.Split('-'); if(versions.Length == 2) { if(versions[0].Trim().Length != 0) brs.OldVersion = new Version(versions[0]); if(versions[1].Trim().Length != 0) brs.OldVersionTo = new Version(versions[1]); if(brs.OldVersion > brs.oldVersionTo) { tempVersion = brs.OldVersion; brs.OldVersion = brs.oldVersionTo; brs.oldVersionTo = tempVersion; } } else brs.OldVersion = new Version(versions[0]); } } } return brs; }