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 事件。(您使用它来欺骗 .NET 以接受正在加载的程序集,即使它不在 GAC 中或与您编译的 DLL 中)

使用代码手动加载引用的 DLL 后,CreateInstance 将起作用。

于 2009-01-22T19:07:40.067 回答
0

first of all i think you have circular dependency .. your last paragraph sums it up. You need to rethink your application and decide if you have responsibilities setup correctly.

Why circular dependency:

For the new dll to be generated it requires MyApp.exe;

MyApp.exe cannot be used without the new dll.

maybe post what your goal is and we can help structure your app correctly.

With proper responsibility delegated MyApp.exe should be making the new generated assembly do work not require MyApp.exe to use objects from the new dll.

Example you should only have Execute on the new generated assembly .....

    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

您确定它在编译时引用了您认为它正在引用的 DLL 实例吗?它可能正在解析到您认为的其他地方的路径,这样在实例化您的类时,它再也找不到该 DLL。我建议获取编译过程和类型创建的 Fusion 日志,以查看如何解析类型。

于 2009-01-22T18:06:47.817 回答
0

我认为.Net 正在尝试在您的 bin 或 GAC 中找到“SomeAdditionalReferencedDLL.dll”。在创建新的 Blah 之前,您是否尝试过为“SomeAdditionalReferencedDLL.dll”执行 Assembly.Load?

于 2009-01-22T18:07:13.230 回答
0

这听起来像您在动态生成的程序集中引用的程序集不在标准探测路径之一中。

相对于其他一切,它位于何处?

您应该启动融合日志查看器以查看哪里出了问题。

于 2009-01-22T18:08:56.503 回答
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 回答