10


5

AssemblyResolveイベントの前に実行時にアセンブリをロードする方法

実際、私は自分の解決策の中で、ある種の「静的にリンクされた」アセンブリを実装しようとしました。 だから私は以下を試してみました:

  • CopyLocal = falseで私のアセンブリへの参照を追加する

  • 「リンクとして追加」を使用して.dllファイル自体を自分のソリューションに追加する

  • 「リソースの追加」-「追加」を使用して、リソースに.dllファイル自体を追加します 既存のファイル '

  • アセンブリから型をForm1に次のように追加します プライベートMyObject temp = new MyObject();

これらのステップの後、私は期待どおりFileNotFoundExceptionを受け取りました。 それでは、このクイックハックでAssemblyResolveEvent内にアセンブリをロードしてみましょう

AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
    {
        Assembly MyAssembly = AppDomain.CurrentDomain.Load(Properties.Resources.ExternalAssembly);
        return MyAssembly;
    };

だからこれはうまくいきます! AssemblyResolveEvent内のリソースファイルから自分のアセンブリを読み込むことができます。 しかし、このイベントは、他の場所で私のアセンブリが見つからなかった場合にのみ発生します。 しかし、どのように私は私のアセンブリをロードすることができます*前に*。ネットは別の場所を検索しようとします?

http://msdn.microsoft.com/en-us/library/aa98tba8.aspx [以前に参照されたアセンブリの確認]の事実により、アセンブリをドメインに事前にロードすることは可能であると考え、これを採用します。 。

次のMain()メソッドを使用して、program.cs内でこれを試しました。

static void Main()
{
    LoadMyAssemblies();
    AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => LoadMyAssemblies();
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

private static Assembly LoadMyAssemblies()
{
    Assembly result = AppDomain.CurrentDomain.Load(Properties.Resources.MyStaticAssembly);
    return result;
}

しかし、それはまだResolveEventHandlerに出くわします。 そして、もっといいのは、もう一度アセンブリをロードして* AppDomain.CurrentDomain.GetAssemblies()を見れば、私のアセンブリが2回ロードされていることがわかります。

それで、私のロードされたアセンブリがAssemblyResolveイベントの前にロードされるときに考慮されない理由は何でもありますか デバッガの助けを借りて、私は呼び出しがAssemblyResolveから来たときにもnullを返しましたが、この場合、最初と同じようにFileNotFoundExceptionを受け取りました。

2 Answer


3


念のため、MS Researchの ILMergeというツールでアセンブリを1つのファイルにマージします。

また、 アセンブリリンカツールを使用してマルチファイルアセンブリを作成することもできます。

さらにあなたの最初の質問に答えるために、私が思うに、ランタイムはあなたが手動でロードしたアセンブリがそれが探しているべきものであることを知らないということです。 そのため、アセンブリを再度読み込むのではなく、アセンブリ解決イベントで、手動で読み込んだアセンブリへの参照を返すだけです。


3


CLR Binderは、LoadMyAssemblies()がAssemblyResolveイベントと同じことをしていること、および両方が同じアセンブリを探してロードしようとしていることを知りません。

AssemblyResolveイベントは、バインダーがすべての可能な場所(そのアプリケーションに対して検索可能)を検索し、一致するものを見つけられなかったと判断した時点で必ず発生します。

これは元々の疑問を投げかけています、なぜあなたはあなたのマネージアセンブリを静的にリンクしたいのですか? 静的リンクの利点についての多くの議論のためにこのスレッドを読んでください。

先に進んで、AssemblyResolveイベントが発生しないようにする方法について説明します。1)アセンブリをGACに配置します。 バインダーに関しては、GACが常に勝ちます。 2)アセンブリをプロービングパスに配置し、Binderがそれを確実に検出するようにします(これについては、MSDNの記事「ランタイムがアセンブリを見つける方法」を参照してください)。