ILMerge程序集并动态加载此合并的程序集

时间:2014-07-25 18:19:48

标签: c# appdomain ilmerge razorengine

情况:

  1. 我合并了两个程序集:Functionality.dll和Models.dll
  2. 功能调用:RazorEngine.Razor.Parse("template", new Models.Model())(简化) (Functionality.dll引用Models.dll和RazorEngine。RazorEngine已添加到GAC。合并程序集不是出于各种原因)
  3. 合并程序集上传到第三方工具。第3方工具将此合并的dll动态加载到其appdomain中并执行它。
  4. 结果:抛出异常: Unable to compile template. The type or namespace name 'Models' could not be found. (are you missing an assembly reference?)

    对我来说这很奇怪,因为'模特' namespace是合并程序集的一部分。如果我检查(使用调试器)它已加载。 (AppDomain.CurrentDomain.GetAssemblies)。 但是:合并的程序集没有位置。 (Assembly.Location ="")。我认为这是因为它是由第三方应用程序动态加载的?这导致RazorEngine抛出此异常,因为它按位置(@params.ReferencedAssemblies.Add(locationofdll))'

    添加对所有已加载程序集的引用

    我的问题是:

    如何确保将动态加载的合并dll(正确)加载到appdomain中,以便RazorEngine可以添加对它的引用?对我来说,将我合并的dll放入GAC并不方便。 (我已将其上传到我的第三方应用程序中)。而第三方应用程序可能有多个服务器。我知道,可以在GAC中添加它,也许这就是GAC的用途,但我只是想知道我是否能够以某种方式将我的合并程序集(再次?)加载到当前运行的AppDomain中(With一个位置?)所以RazorEngine可以添加一个引用。 (奇怪吧?RazorEngine.dll在与合并的dll相同的AppDomain中运行。我对其进行了双重检查)

    很长的问题。对不起。我希望有人可以给我一些关于如何将它们挂在一起的指针(AppDomain,动态加载,使用GAC程序集(RazorEngine)合并的程序集,需要知道合并程序集中的类型.... pfft)

    谢谢!

1 个答案:

答案 0 :(得分:0)

这是(正如您已经注意到的),因为RazorEngine会忽略具有null位置的所有程序集。虽然我无法给你一个确切的答案,但我可能会给你一些提示/解决方法(在RazorEngine问题的具体部分)。

旧版本(< 3.5.0)中没有太多可以做的事了:

基本上你需要加载RazorEngine代码作为具有非null位置属性的程序集(我不知道在你的情况下是否有办法做到这一点)。 您是否真的尝试通过Assembly.LoadFrom方法再次加载程序集? 如果这不起作用,您可以在新的Assembly中正确加载AppDomain并在那里进行编译。 一旦引用加载了非null位置属性RazorEngine,就应该选择它...

在较新版本上(等待下一个版本(> = 3.5.0)或从develop分支构建): 您可以使用IReferenceResolver界面解决这种情况。

  • 您知道程序集的位置,并且可以手动将该路径添加到返回的集合中(仅使用From(string)重载):

    class MyIReferenceResolver : IReferenceResolver {
        public IEnumerable<CompilerReference> GetReferences(TypeContext context, IEnumerable<CompilerReference> includeAssemblies) {
            // add all references needed by the compilation of the template
            // You should include the includeAssemlies as well :)
            return new [] { 
                CompilerReference.From("Path-to-my-custom-assembly"), // file path (string)
                CompilerReference.From(typeof(MyType).Assembly), // Assembly (roslyn only in your situation)
                CompilerReference.From(assemblyInByteArray), // byte array (roslyn only)
                CompilerReference.From(File.OpenRead(assembly)), // stream (roslyn only)
            };
        }
    }
    

    然后在配置

    中设置它
    config.ReferenceResolver = new MyIReferenceResolver();
    

    文档为here

  • 如果您不知道装配的位置: 尝试使用Roslyn编译器和CompilerReference.From(typeof(MyType).Assembly)引用。文档为herehere

资料来源:我目前向RazorEngine项目提供了新的API。

注意:在我们正确发布之前,确切的界面可能会发生变化。