5

クラスのソースコードを動的に作成してコンパイルするアプリ(MyAppと呼びましょう)があります。ソース コードをコンパイルするときに、別のフォルダーに既に存在する別の DLL (この新しく作成されたクラスの基本クラス) も参照します。DLL をコンパイルして出力するには、次のようにします。

//Create a C# code provider 
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

//Set the complier parameters
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = false;
cp.GenerateInMemory = false;
cp.TreatWarningsAsErrors = false;
cp.WarningLevel = 3;
cp.OutputAssembly = "SomeOutputPathForDLL";

// Include referenced assemblies
cp.ReferencedAssemblies.Add("mscorlib.dll");
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("System.Core.dll");
cp.ReferencedAssemblies.Add("System.Data.dll");
cp.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");
cp.ReferencedAssemblies.Add("System.Xml.dll");
cp.ReferencedAssemblies.Add("System.Xml.Linq.dll");
cp.ReferencedAssemblies.Add("MyApp.exe");
cp.ReferencedAssemblies.Add("SomeFolder\SomeAdditionalReferencedDLL.dll");

// Set the compiler options
cp.CompilerOptions = "/target:library /optimize";
CompilerResults cr = provider.CompileAssemblyFromFile(cp, "PathToSourceCodeFile");

後でアプリで (または次回アプリを実行するときに) クラスのインスタンスを作成しようとします。新しく作成されたクラス (Blah と呼びましょう) の DLL と基本クラスの両方がどこにあるかはわかっています。次のコードを使用して、新しいクラスのインスタンスを作成しようとします。

Assembly assembly = Assembly.LoadFile("PathToNewClassDLL");
Blah newBlah = assembly.CreateInstance("MyApp.BlahNamespace.Blah") as Blah;

上記のように Assembly.CreateInstance を呼び出すと、インスタンスを作成できないというエラーが表示されます。assembly.GetReferencedAssemblies() を確認すると、標準参照とアプリ (MyApp.exe) の参照が含まれていますが、最初にクラスをコンパイルするときに使用した依存基本クラス (SomeAdditionalReferencedDLL.dll) の参照はありません。 .

インスタンスを作成するために何らかの方法で基本クラスの参照を追加する必要があることはわかっていますが、これを行う方法がわかりません。アセンブリとそのすべての依存関係がある場合、アセンブリからクラスのインスタンスを作成するにはどうすればよいですか?

ありがとう

4

6 に答える 6

3

外部 DLL (アセンブリ) を手動でロードすると、参照した内容が自動的にロードされません。

したがって、AssemblyLoader を作成する必要があります。アセンブリの参照アセンブリをチェックし、それらを自分で読み込むコード。

コンピューターの奇妙なフォルダーにあり、コンパイル済みの DLL と一緒に存在しない参照アセンブリに関する複雑な問題については、AppDomain.CurrentDomain.AssemblyResolve イベントを確認してください。(GAC やコンパイル済みの DLL にない場合でも、.NET をだましてアセンブリのロードを受け入れるために使用します)

参照する DLL をコードで手動でロードすると、CreateInstance が機能します。

于 2009-01-22T19:07:40.067 に答える
0

コンパイル時に、参照していると思われる DLL のインスタンスを参照したことは確かですか? クラスをインスタンス化するときに、そのDLLを見つけることができなくなると思われる場所以外の場所へのパスを解決している可能性があります。コンパイル プロセスと型作成の両方の Fusion ログを取得して、型がどのように解決されているかを確認することをお勧めします。

于 2009-01-22T18:06:47.817 に答える
0

.Net は、ビンまたは GAC で「SomeAdditionalReferencedDLL.dll」を見つけようとしていると思います。新しい Blah を作成する前に、「SomeAdditionalReferencedDLL.dll」の Assembly.Load を実行しようとしましたか?

于 2009-01-22T18:07:13.230 に答える
0

これは、動的に生成されたアセンブリで参照しているアセンブリが、標準のプローブ パスのいずれにもないように聞こえます。

他のすべてのものと比べて、それはどこにありますか?

フュージョン ログ ビューアを起動して、どこで問題が発生しているかを確認する必要があります。

于 2009-01-22T18:08:56.503 に答える
0

まず第一に、循環依存関係があると思います..最後の段落がそれを要約しています。アプリケーションを再考し、責任が正しく設定されているかどうかを判断する必要があります。

循環依存の理由:

新しい dll を生成するには、MyApp.exe が必要です。

MyApp.exe は、新しい dll がないと使用できません。

多分あなたの目標が何であるかを投稿してください。私たちはあなたのアプリを正しく構築するのを助けることができます.

適切な責任を委任された MyApp.exe は、新しく生成されたアセンブリを機能させる必要があり、MyApp.exe が新しい dll のオブジェクトを使用する必要はありません。

新しく生成されたアセンブリでのみ実行する必要がある例.....

    public static void RenderTemplate(String templatepath, System.IO.Stream outstream, XElement xml, Dictionary<String, object> otherdata)
    {
        var templateFile = System.IO.File.ReadAllText(templatepath);

        var interpreter = new Interpreter();
        interpreter.ReferencedAssemblies.Add("System.Core.dll"); // linq extentions
        interpreter.ReferencedAssemblies.Add("System.Xml.dll");
        interpreter.ReferencedAssemblies.Add("System.Xml.Linq.dll");

        interpreter.UsingReferences.Add("System.Linq");
        interpreter.UsingReferences.Add("System.Xml");
        interpreter.UsingReferences.Add("System.Xml.Linq");
        interpreter.UsingReferences.Add("System.Collections.Generic");
        interpreter.Execute(templateFile, outstream, xml, otherdata);
    }
于 2009-07-18T20:40:40.533 に答える
0
//Constructor
static MyClass()
    {
        //Provoque l'événement quand .Net ne sait pas retrouver un Assembly référencé
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

    }
    /// <summary>
    /// Mémorise les assembly référencés par d'autres qui ne sont pas dans le répertoire principal d'EDV
    /// </summary>
    static Dictionary<string, string> _AssembliesPath;
    /// <summary>
    /// .Net ne sait pas retrouver un Assembly référencé
    /// Cherche et charge d'après les assembly référencés par d'autres qui ne sont pas dans le répertoire principal d'EDV        
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    /// <returns></returns>
    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        if (_AssembliesPath != null && _AssembliesPath.ContainsKey(args.Name))
        {
            Assembly lAssembly = Assembly.LoadFile(_AssembliesPath[args.Name]);
            AddAssemblyReferencedAssemblies(lAssembly, System.IO.Path.GetDirectoryName(lAssembly.Location));
            return lAssembly;
        }
        Error = string.Format("L'assembly {0} n'a pu être chargé", args.Name);
        return null;
    }
    /// <summary>
    /// Mémorise les assembly référencés par d'autres qui ne sont pas dans le répertoire principal d'EDV        
    /// </summary>
    /// <param name="pAssembly"></param>
    /// <param name="psRootPath"></param>
    static void AddAssemblyReferencedAssemblies(Assembly pAssembly, string psRootPath)
    {
        if (_AssembliesPath == null) _AssembliesPath = new Dictionary<string, string>();
        foreach (AssemblyName lRefedAss in pAssembly.GetReferencedAssemblies())
            if (!_AssembliesPath.ContainsKey(lRefedAss.FullName))
            {
                string lsRoot = psRootPath + "\\" + lRefedAss.Name + ".";
                string lsExt;
                if (System.IO.File.Exists(lsRoot + (lsExt = "dll")) || System.IO.File.Exists(lsRoot + (lsExt = "exe")))
                {
                    _AssembliesPath.Add(lRefedAss.FullName, lsRoot + lsExt);
                }
            }
    }

//関数呼び出し Assembly lAssembly = Assembly.LoadFile(lsExternalAssemblyPath); AddAssemblyReferencedAssemblies(lAssembly, System.IO.Path.GetDirectoryName(lsExternalAssemblyPath));

于 2010-06-01T08:33:34.350 に答える