0

部分的な名前に基づいてGACにアセンブリをロードできるようにする必要がある状況があります。これを行うために、app.configファイルに以下を追加しました。

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <qualifyAssembly partialName="MyAssembly"
                     fullName= "MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0123456789abcdef"/>
  </assemblyBinding>
</runtime>

これは私が望むように正確に機能します。ただし、machine.configファイルに同じ要素を配置すると、無視されているように見え、MyAssemblyを読み込もうとするとFileNotFoundExceptionsが発生します。

以下は、要素がapp.configにあり、バインドが成功した場合のアセンブリバインディングログです。

ログ:このバインドは、デフォルトのロードコンテキストで開始されます。
ログ:アプリケーション構成ファイルの使用:C:\ Documents and Settings \ jon_scheiding \ My Documents \ Source \ Testing \ Test Projects 1 \ Cmd \ bin \ Debug \ Testers.Cmd.vshost.exe.config
ログ:C:\ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 \ config\machine.configのマシン構成ファイルを使用しています。
ログ:構成ファイルから修飾された部分参照。新しい参照:MyAssembly、Version = 1.0.0.0、Culture = neutral、PublicKeyToken=0123456789abcdef。
ログ:ポリシー後の参照:MyAssembly、Version = 1.0.0.0、Culture = neutral、PublicKeyToken = 0123456789abcdef
ログ:GACを調べてアセンブリを見つけました。
ログ:バインドは成功します。C:\ WINDOWS \ assembly \ GAC_MSIL \ MyAssembly \ 1.0.0.0__b20f4683c1030dbd\MyAssembly.dllからアセンブリを返します。
ログ:アセンブリはデフォルトのロードコンテキストでロードされます。

構成がmachine.configにあり、バインドが失敗した場合のログと比較してください。

ログ:このバインドは、デフォルトのロードコンテキストで開始されます。
ログ:アプリケーション構成ファイルの使用:C:\ Documents and Settings \ jon_scheiding \ My Documents \ Source \ Testing \ Test Projects 1 \ Cmd \ bin \ Debug \ Testers.Cmd.vshost.exe.config
ログ:C:\ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 \ config\machine.configのマシン構成ファイルを使用しています。
ログ:現時点では、ポリシーは参照に適用されていません(プライベート、カスタム、部分的、またはロケーションベースのアセンブリバインド)。
ログ:新しいURLファイルのダウンロードを試みています:/// C:/ Documents and Settings / jon_scheiding / My Documents / Source / Testing / Test Projects 1 / Cmd / bin / Debug/MyAssembly.DLL。
ログ:新しいURLファイルのダウンロードを試みています:/// C:/ Documents and Settings / jon_scheiding / My Documents / Source / Testing / Test Projects 1 / Cmd / bin / Debug / MyAssembly/MyAssembly.DLL。
ログ:新しいURLファイルのダウンロードを試みています:/// C:/ Documents and Settings / jon_scheiding / My Documents / Source / Testing / Test Projects 1 / Cmd / bin / Debug/MyAssembly.EXE。
ログ:新しいURLファイルのダウンロードを試みています:/// C:/ Documents and Settings / jon_scheiding / My Documents / Source / Testing / Test Projects 1 / Cmd / bin / Debug / MyAssembly/MyAssembly.EXE。
ログ:すべてのプロービングURLが試行され、失敗しました。

問題は、「現時点ではポリシーが参照に適用されていない」という4行目であるようです。ただし、このメッセージの意味や対処方法に関するドキュメントはほとんど見つかりません。

フレームワークに<runtime>要素を認識させるにはどうすればよいですか?

前もって感謝します!

4

2 に答える 2

2

GACにはいくつかのアセンブリがあり、それらを解決するためにNHibernateのようなものが必要だったので、私はこの必要性にかなり後で戻ってきました。これらすべてのqualifyAssembly要素をすべてのapp.configに追加するのではなく、次のコードを使用すると、それらをmachine.configに追加できます.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.XPath;

namespace MyNamespace {

    /// <summary>
    /// Implements <see cref="IDisposable"/> to provide a scope for resolving
    /// assemblies described in the machine.config file with 
    /// &lt;qualifyAssembly&gt; elements.
    /// </summary>
    /// <remarks>
    /// Because the framework only respects &lt;qualifyAssembly&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 <b>using</b> statement
    /// to get resolution within a specific scope; or, you can call the 
    /// <see cref="AssemblyResolver.Attach()"/> method to get 
    /// resolution for the lifetime of the current <see cref="AppDomain"/>.
    /// </remarks>
    public sealed class AssemblyResolver : IDisposable {

        #region Private fields and implementation

        private static Dictionary<string, string> _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<string, string> BuildQualifiedNameList() {
            var dict = new Dictionary<string, string>(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

        /// <summary>
        /// Creates a new <see cref="AssemblyResolver"/>.
        /// </summary>
        public AssemblyResolver() {
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
        }

        /// <summary>
        /// Removes the current <see cref="AssemblyResolver"/>
        /// from the <see cref="AppDomain"/>.
        /// </summary>
        public void Dispose() {
            AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(ResolveAssembly);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Provides qualified assembly resolution for the lifetime of the
        /// current <see cref="AppDomain"/>.
        /// </summary>
        public static void Attach() {
            Attach(AppDomain.CurrentDomain);
        }

        /// <summary>
        /// Provides qualified assembly resolution for the lifetime of an
        /// <see cref="AppDomain"/>.
        /// </summary>
        /// <param name="appDomain">
        /// The <see cref="AppDomain"/> to service.
        /// </param>
        public static void Attach(AppDomain appDomain) {
            appDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
        }

    }
}

ほとんどの場合、次のように使用して範囲を制限します。

using(new AssemblyResolver()) {
    //
    // NHibernate initialization or whatever
    //
}

また、アプリのスタートアップ コードまたは global.asax で使用することもでき、次のように、アプリケーションの存続期間中保持されます。

AssemblyResolver.Attach();
//
// or
//
AssemblyResolver.Attach(AppDomain.CurrentDomain);
于 2011-02-04T16:03:54.733 に答える
2

フレームワークは、qualifyAssebmly 構成を machine.config から読み取るのではなく、アプリケーション構成ファイルから読み取るだけです。

フレームワークは runtim 要素を認識しますが、qualifyAssembly 要素は認識しません。

于 2008-12-03T07:17:01.107 に答える