2009-07-21 64 views
10

実際、私は私のソリューションの中で何らかの「静的にリンクされた」アセンブリを実装しようとしました。AssemblyResolveイベントの前に実行時にassembyをロードする方法はありますか?

  • CopyLocalが= falseを
  • .dllファイル自体への追加
  • 「リンクとして追加」で私の解決策に.dllファイル自体を追加すると、私のアセンブリへの参照を追加:だから私は次のことを試してみました期待通りの手順は、私がしてFileNotFoundExceptionを得た後private MyObject temp = new MyObject();

としてのForm1への私のアセンブリの外にいくつかのタイプを追加

  • 「既存のファイルを追加します。」 - 「リソースの追加」を持つ自分のリソース。それでは、だから、これは動作しますこのクイックハック

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

    でAssemblyResolveEvent内のアセンブリをロードしてみましょう! AssemblyResolveEvent内のリソースファイルからアセンブリをロードできます。しかし、このイベントは、他の場所で私のアセンブリが見つからない場合にのみ発生します。しかし、どうすれば私のアセンブリをロードすることができますの前に .Netは、さまざまな場所を検索しようとしますか?

    Checking for Previously Referenced Assembliesの事実のため、私はドメインに事前にアセンブリをロードすることが可能であると考えていました。

    は、私は次のメイン()メソッド

    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; 
    } 
    

    を使用してのProgram.cs内にこれを試してみました。しかし、それはまだResolveEventHandlerに実行されます。そして、はるかに良い、私はアセンブリを再度ロードして見てAppDomain.CurrentDomain.GetAssemblies()私のアセンブリが2回ロードされていることがわかります!

    AssemblyResolveイベントの前にロードされたアセンブリがロードされたときに、ロードされたアセンブリが考慮されない理由は何ですか?デバッガの助けを借りて、私はAssemblyResolveからコールが来たときにnullを返しましたが、この場合、私は最初にFileNotFoundExceptionを取得しました。

  • 答えて

    3

    あなたが知らなかった場合には、MS ResearchのILMergeというツールがあり、アセンブリを1つのファイルにマージします。

    Assembly Linker toolを使用してマルチファイルアセンブリを作成することもできます。

    プラス私が考える問題は、手動でロードしたアセンブリが探しているはずであることをランタイムが知らないということです。したがって、アセンブリを再度ロードするのではなく、アセンブリ解決イベントで、手動でロードしたアセンブリへの参照を渡してください。

    +0

    ILMergeはすでにいくつかの状況で使用されていますが、この場合は「最良の」解決策ではありません。同じアセンブリがプログラムフォルダまたはGACにある場合、これは実行され、イベントはスローされないため、同じアセンブリを元の位置に戻すことも良い解決策ではありません。 – Oliver

    3

    CLRバインダーは、AssemblyResolveイベントと同じことをLoadMyAssemblies()が認識しておらず、同じアセンブリを探してロードしようとしています。

    AssemblyResolveイベントは、バインダーが(アプリケーションで検索可能な)すべての可能な場所を検索し、一致するものが見つからないと判断した時点で常に起動されます。

    これは、なぜ管理対象アセンブリを静的にリンクしたいのですかという最初の質問をします。このスレッドをよくお読みくださいStatic linking advantages

    AssemblyResolveイベントを回避する方法については、私が先にお答えします。 1)アセンブリをGACに入れてください。バインダーに関しては、GACは常に勝ちます。 2)アセンブリをプロービングパスに置き、バインダがそれをピックアップすることを確認します(この詳細については、MSDNの記事「ランタイムのアセンブリの検索方法」を参照してください)。

    +0

    あなたはそうです、CLRバインダーは私の機能について何も知りません。しかし、既に言及したように、AssemblyResolveイベントは、すべての可能な場所を検索したときに起動します。しかし、それは本当ではありません!現在のAppDomain内のロードされたアセンブリのリストを調べていないだけです!しかし、これを読んだら(http://msdn.microsoft.com/en-us/library/aa98tba8.aspx)、そこに見えるはずです。 – Oliver

    関連する問題