引用动态创建的类中的嵌入程序集

本文关键字:程序集 动态 创建 引用 | 更新日期: 2023-09-27 17:59:06

我一直在使用将dll(嵌入式资源)嵌入到exe中的技术,并使用以下代码在运行时解析未知的dll。

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    String resourceName = "Project.lib." + new AssemblyName(args.Name).Name + ".dll";
    using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
    {
        Byte[] assemblyData = new Byte[stream.Length];
        stream.Read(assemblyData, 0, assemblyData.Length);
        return Assembly.Load(assemblyData);
    }
};

然而,当我嵌入Spark View Engine dll(例如)时,它会失败。但只在一个特定的地方。Spark本身动态地动态生成类。然后,这些类引用Spark(using Spark等)。就在这一点上,我得到了以下错误。

类型"Spark.Class"在中定义未被引用的程序集。必须添加对组件"Spark"

我确信这与Spark视图引擎无关,而是与从动态生成的类中引用嵌入的程序集有关。

更新:堆栈跟踪

运行时发生异常项目任务消息:Spark.Compiler.BatchCompilerException:动态视图编译失败。c: ''Users''Adam''AppData''Local''Temp''kdsjyhvu.0.cs(6,14):错误CS0012:类型已定义"Spark.AbstractSparkView"在未被引用的程序集中。必须添加对程序集的引用'Spark,版本=1.5.0.0,文化=中性,PublicKeyToken=7f8549eed921a12c'Spark.Compiler.BatchCompiler.Compile(布尔调试,字符串语言或扩展,String[]sourceCode)Spark.Compiler.CSharp.CSharpViewCompiler.CompileView(IEnumerable 1 viewTemplates, IEnumerable 1allResources)Spark.SparkViewEngine.CreateEntryInternal(SparkViewDescriptor描述符,布尔编译)Spark.SparkViewEngine.CreateEntry(SparkViewDescriptor描述符)Spark.SparkViewEngine.CreateInstance(SparkViewDescriptor描述符)ProjectTasks.Core.Template.Populate(字符串templateFilePath,对象数据)''项目任务''核心''模板.cs:line33项目任务。。Core.EmailTemplates.RenderImpl(字符串名称,对象数据)''项目任务''核心''电子邮件模板.cs:line19ProjectTasks.Tasks.EmailUsersWithIncompleteModules.Run()在里面''ProjectTasks''Tasks''EmailUsersWithIncompleteModules.cs:line41 atProjectTasks.MaintenanceTaskRunner.Run(布尔值runNow,IMaintenanceTask[]任务)''ProjectTasks''MaintenanceTaskRunner.cs:line25 atProjectTasks.Initializer.Init(String[]args)''项目任务''初始化程序.cs:line30

如果真的有决议的话,有人对决议有什么想法吗?

引用动态创建的类中的嵌入程序集

我猜Spark使用CodeDom进行动态代码生成。CSharpCodeProvider内部生成源代码并运行csc.exe以获取新类型。由于csc.exe需要物理文件作为引用,因此AssemblyResolve技巧在这种情况下没有帮助。

堆栈跟踪强烈表明Spark正在使用System.CodeDom动态生成程序集。这要求引用程序集必须是磁盘上的文件,C#编译器会耗尽进程。这通常不是问题,因为Spark.dll与EXE位于同一目录中。

你无法做到这一点。

Fwiw:这种技术非常浪费系统资源。将程序集所需的内存量增加一倍。它也是一种昂贵的内存,不能在进程之间共享,并且由分页文件而不是程序集文件支持。你也可以给自己买一些严重的类型身份问题。NET已经支持在单个文件中进行部署。它被称为setup.exe

正如其他人所说,问题在于CodeDom在磁盘上生成工件,然后需要访问这些工件才能渲染视图。

除了嵌入Spark可能占用内存之外,我相信这个问题还有一个潜在的解决方案。考虑到这个问题是由动态视图生成引起的,为什么不利用Spark的批编译选项为视图生成dll作为构建的一部分呢。

你可以使用类似于以下的代码来实现这一点:

var factory = new SparkViewFactory(settings)
               {
                   ViewFolder = new FileSystemViewFolder(viewsLocation)
               };
// And generate all of the known view/master templates into the target assembly
var batch = new SparkBatchDescriptor(targetPath);
factory.Precompile(batch);

最后,你应该有一个包含编译视图的输出dll,然后你可以像嵌入主Spark.dll一样嵌入该dll。

希望能有所帮助
Rob