问题描述
|
我一直在使用将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,assemblyData.Length);
return Assembly.Load(assemblyData);
}
};
但是,当我嵌入Spark View Engine dll(例如)时,它掉落了。但是只在一个特定的地方。 Spark本身可以动态地动态生成类。这些类然后引用Spark(using Spark
等)。正是在这一点上,我得到以下错误。
类型\'Spark.Class \'在以下位置定义
未引用的程序集。
您必须添加对
程序集“火花”
我很确定这与Spark视图引擎无关,而与从动态生成的类中引用嵌入式程序集有关。
更新:stacktrace
运行时发生异常
项目任务消息:
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 languageOrExtension,
String [] sourceCode)
Spark.Compiler.CSharp.CSharpViewCompiler.CompileView(IEnumerable1
viewTemplates,IEnumerable
1
allResources)
Spark.SparkViewEngine.CreateEntryInternal(SparkViewDescriptor
描述符,布尔编译)在
Spark.SparkViewEngine.CreateEntry(SparkViewDescriptor
描述符)
Spark.SparkViewEngine.CreateInstance(SparkViewDescriptor
描述符)
ProjectTasks.Core.Templater.Populate(String
templateFilePath,对象数据)
\\ ProjectTasks \\ Core \\ Templater.cs:line
33在
ProjectTasks..Core.EmailTemplates.RenderImpl(String
名称,对象数据)
\\ ProjectTasks \\ Core \\ EmailTemplates.cs:line
19点
ProjectTasks.Tasks.EmailUsersWithIncompleteModules.Run()
在
\\ ProjectTasks \\ Tasks \\ EmailUsersWithIncompleteModules.cs:line
41岁
ProjectTasks.MaintenanceTaskRunner.Run(布尔
runNow,ImaintenanceTask []任务)
\\ ProjectTasks \\ MaintenanceTaskRunner.cs:line
25点
ProjectTasks.Initialiser.Init(String []
args)在
\\ ProjectTasks \\ Initialiser.cs:line
30
如果确实有解决方案,有人对解决方案有任何想法吗?
解决方法
我猜Spark使用CodeDom进行动态代码生成。 CSharpCodeProvider在内部生成源代码并运行csc.exe以获取新类型。由于csc.exe需要物理文件作为参考,因此AssemblyResolve技巧在这种情况下将无济于事。
, 堆栈跟踪强烈表明Spark正在使用System.CodeDom动态生成程序集。这要求引用程序集是磁盘上的文件,C#编译器进程外运行。这通常不是问题,因为您将在与EXE相同的目录中拥有Spark.dll。
您无法完成这项工作。
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。
希望能有所帮助
抢