12

まず、これはこのスレッドの質問とは少し異なることを強調する必要があります。さらに、KB2468871をインストールしても役に立ちません。

この問題をできるだけ単純化しようとしました。一般に、Assembly.LoadFile(...) を使用してデスクトップ アプリケーションに PCL アセンブリをロードすることについてです。

.NET 4.0 コンソール アプリケーション (「C」と呼ばれる) があるとします。.NET 4.0 アセンブリ (「N4」と呼ばれる) および PCL アセンブリ (「PCL」と呼ばれる) を参照します。

N4 は次のようになります。

using System.Linq;

namespace N4
{
    public class ClassInN4
    {
        public static string Greet()
        {
            return new string(
                "hello from N4"
                .ToCharArray()
                .Select(char.ToUpper)
                .ToArray()
            );
        }
    }
}

PCL は次のようになります。

using System.Linq;

namespace PCL
{
    public class ClassInPCL
    {
        public static string Greet()
        {
            return new string(
                "hello from pcl"
                .ToCharArray()
                .Select(char.ToUpper)
                .ToArray()
            );
        }
    }
}

C は次のようになります。

using System;
using System.IO;
using System.Reflection;
using N4;
using PCL;

namespace C
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Test();
            Console.ReadLine();
        }

        private static void Test()
        {
            Test("N4", ClassInN4.Greet);
            Test("PCL", ClassInPCL.Greet);
        }

        private static void Test(
            string title, 
            Func<string> generator)
        {
            try
            {
                Console.WriteLine(
                    "{0}: {1}", title, generator());
            }
            catch (Exception e)
            {
                Console.WriteLine(
                    "{0}: {1} -> {2}", title, e.GetType(), e.Message);
            }
        }
    }
}

このアプリケーションを実行すると、完全に正しい結果が得られます。

N4: HELLO FROM N4
PCL: HELLO FROM PCL

Program.Main の CurrentDomain に AssemblyResolve イベントを追加しましょう。

AppDomain.CurrentDomain.AssemblyResolve += (_, a) => {
    var fileName = Path.GetFullPath(
        new AssemblyName(a.Name).Name + ".data");
    Console.WriteLine("Probing '{0}'", fileName);
    return 
        File.Exists(fileName) 
        ? Assembly.LoadFile(fileName) 
        : null;
};

したがって、アセンブリが見つからない場合、「.data」ファイルからロードしようとします。

アプリケーション フォルダに移動し、「N4.dll」を「N4.data」に名前変更して、「C.exe」を実行します。

Probing 'C:\xxx\C\bin\Debug\N4.data'
N4: HELLO FROM N4
PCL: HELLO FROM PCL

そのため、AssemblyResolve を通過し、最終的に「N4.data」をロードして、オリジナルと同じように機能します。

「N4.data」を「N4.dll」に戻し、「PCL.dll」の名前を「PCL.data」に変更して...

Probing 'C:\xxx\C\bin\Debug\PCL.data'
N4: HELLO FROM N4
Probing 'C:\xxx\C\bin\Debug\System.Core.data'
Probing 'C:\xxx\C\bin\Debug\System.Core.data'
Probing 'C:\xxx\C\bin\Debug\System.Core.data'
PCL: System.IO.FileNotFoundException -> Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The system cannot find the file specified.

PCL アセンブリが正常に読み込まれたことに注意してください。問題は、依存関係 (System.Core) しか見つからないことです。

ロードされたアセンブリが移植可能である場合、 Assembly.LoadFile(fileName) はノーノーのようです。

誰かがこの問題を抱えていましたか?誰かがこの問題を解決しましたか?

ここですべてのファイルを見つけることができます。

編集: 他のオプションをチェックするように強制してくれたleppieに感謝します。「ええ、ええ、試しました」と答える間、私は実際に嘘をついていないことを確認したかった. どうやらそれはチェックする価値がありました。

Suzanne Cook の .NET CLR Notesから:

注意してください - これらは同じものではありません。

LoadFrom() は Fusion を通過し、別のパスにある別のアセンブリにリダイレクトできますが、LoadFrom コンテキストに既に読み込まれている場合は同じ ID でリダイレクトできます。LoadFile() は Fusion を介してまったくバインドしません。ローダーは先に進み、呼び出し元が要求したものを正確に*ロードします。Load コンテキストも LoadFrom コンテキストも使用しません。

4

3 に答える 3

5

バージョンを尋ねられたら、イベントからSystem.Coreプラットフォームのアセンブリ (例: version 4.0.0.0 for .NET Framework 4.0)を返すことができます。AssemblyResolve2.0.5.0

を介してリソースとして保存されているすべての参照アセンブリをロードしていLoad(byte[])ますが、これもアセンブリの解決に失敗し2.0.5.0、 と の両方を取得してSystemSystem.CoreますAppDomain.CurrentDomain.GetAssemblies()

于 2013-09-01T18:49:10.830 に答える
1

私は同じ問題を抱えていて、次の解決策に行き着きました: PCL アセンブリを動的にロードする前に、次のコードを呼び出します。

Assembly.Load("System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes");
Assembly.Load("System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes");

PCL アセンブリをロードするときに他の依存関係が欠落している場合は、上記のコードに行を追加するだけです。奇妙で理解できない理由で、それは機能します。

于 2016-11-12T11:10:00.393 に答える