c# – Roslyn – 从内存中组装创建MetadataReference
使用ASP.NET 5应用程序(Visual Studio 2015 CTP5)和Microsoft.CodeAnalysis.CSharp.
如果我尝试创建一个MetadataReference到一个程序集,该程序集是解决方案的一部分,将其作为对CSharpCompilation.Create的引用传递,我得到一个System.ArgumentException,“空路径名称不合法”. // Throws exception MetadataReference.CreateFromAssembly(typeof(this).Assembly); // Doesn't throw exception MetadataReference.CreateFromAssembly(typeof(Object).Assembly); 如果我检查程序集的Location属性,它是空的.我假设这与在ASP.NET 5中编译内存中应用程序的新方法有关,因此程序集不会存储在光盘上. 那么有没有办法将Roslyn的引用传递给没有Location属性的程序集,或者目前是不支持的? 编辑: System.ArgumentException Empty path name is not legal. C:DevelopmentIncubatornet.frameworksrcWebfuel.Services.HostScriptHelperScriptHelper.cs Line 86: Line 87: // Compile the code Line 88: var compilation = CSharpCompilation.Create( Line 89: assemblyName,Line 90: options: new CSharpCompilationOptions(outputKind: OutputKind.DynamicallyLinkedLibrary),at System.IO.FileStream.Init(String path,FileMode mode,FileAccess access,Int32 rights,Boolean useRights,FileShare share,Int32 bufferSize,FileOptions options,Win32Native.SECURITY_ATTRIBUTES secAttrs,String msgPath,Boolean bFromProxy,Boolean useLongPath,Boolean checkHost) at System.IO.FileStream..ctor(String path,FileShare share) at System.IO.File.OpenRead(String path) at Microsoft.CodeAnalysis.InternalUtilities.FileStreamLightUp.OpenFileStream(String path) at Microsoft.CodeAnalysis.MetadataReference.CreateFromAssembly(Assembly assembly,MetadataReferenceProperties properties,DocumentationProvider documentation) at Microsoft.CodeAnalysis.MetadataReference.CreateFromAssembly(Assembly assembly) at Webfuel.Services.Host.ScriptHelper.CompileScriptImpl(String source) in C:DevelopmentIncubatornet.frameworksrcWebfuel.Services.HostScriptHelperScriptHelper.cs:line 88 at Webfuel.Services.Host.ScriptHelper.<>c__DisplayClass0.<CompileTemplate>b__3(String source) in C:DevelopmentIncubatornet.frameworksrcWebfuel.Services.HostScriptHelperScriptHelper.cs:line 71 at System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue>.GetOrAdd(TKey key,Func<TKey,TValue> valueFactory) at Webfuel.Services.Host.ScriptHelper.CompileTemplate(String template) in C:DevelopmentIncubatornet.frameworksrcWebfuel.Services.HostScriptHelperScriptHelper.cs:line 69 at Webfuel.Services.Host.SandboxContext.<ExecuteTemplateAsync>d__1.MoveNext() in C:DevelopmentIncubatornet.frameworksrcWebfuel.Services.HostSandboxContext.cs:line 176 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter<TResult>.GetResult() at Webfuel.Services.Host.SandboxHost.<ExecuteTemplateAsync>d__1.MoveNext() in C:DevelopmentIncubatornet.frameworksrcWebfuel.Services.HostSandboxHost.cs:line 39 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter<TResult>.GetResult() at Webfuel.Services.Sandbox.SandboxService.<ExecuteTemplateAsync>d__1.MoveNext() in C:DevelopmentIncubatornet.frameworksrcWebfuel.Services.SandboxSandboxService.cs:line 47 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter<TResult>.GetResult() at Webfuel.Services.Server.ServerService.<ProcessContentRequestAsync>d__1.MoveNext() in C:DevelopmentIncubatornet.frameworksrcWebfuel.Services.ServerServerService.cs:line 179 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter<TResult>.GetResult() at Webfuel.Services.Server.ServerService.<ProcessRequestAsync>d__1.MoveNext() in C:DevelopmentIncubatornet.frameworksrcWebfuel.Services.ServerServerService.cs:line 73 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter<TResult>.GetResult() at Webfuel.App.ServerMiddleware.<Invoke>d__1.MoveNext() in C:DevelopmentIncubatornet.frameworksrcWebfuel.AppStartup.cs:line 89 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNet.RequestContainer.ContainerMiddleware.<Invoke>d__1.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNet.Loader.IIS.KlrHttpApplication.<ProcessRequestAsyncImpl>d__1.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.AspNet.Loader.IIS.HttpApplicationBase.<InvokeProcessRequestAsyncImpl>d__1.MoveNext() 解决方法
已经有一段时间了,但我确实在github Roslyn存储库上得到了答案,所以如果有人发现这个问题,我会发布它:
ASP.NET 5有一个API.你可以做Razor做的https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs#L132 这回到了Asp.Net 5的Beta1左右,所以可能需要调整但原理仍然相同 – 遵循Asp.Net本身通过服务注入器将提供的IAssemblyLoadContextAccessor使用的API. 感谢David Fowler 更新:这个答案是针对ASP.NET 5 Beta1的. API发生了很大变化,在Core 1.0中,而不是使用IAssemblyLoadContextAccessor,您可以从静态成员访问AssemblyLoadContext: System.Runtime.Loader.AssemblyLoadContext.Default 然后,您可以调用LoadFromStream从二进制映像加载程序集.这是我使用的代码的一个非常粗略的草图,其中一些不相关的部分被破解: // Give the assembly a unique name var assemblyName = "Gen" + Guid.NewGuid().ToString().Replace("-","") + ".dll"; // Build the syntax tree var syntaxTree = CSharpSyntaxTree.ParseText(source); // Compile the code var compilation = CSharpCompilation.Create( assemblyName,options: new CSharpCompilationOptions(outputKind: OutputKind.DynamicallyLinkedLibrary),syntaxTrees: new List<SyntaxTree> { syntaxTree },references: GetMetadataReferences()); // Emit the image of this assembly byte[] image = null; using (var ms = new MemoryStream()) { var emitResult = compilation.Emit(ms); if (!emitResult.Success) { throw new InvalidOperationException(); } image = ms.ToArray(); } Assembly assembly = null; // NETCORE using (var stream = new MemoryStream(image)) assembly = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromStream(stream); 这不应该按原样运行,而只是想一想主要步骤. 此外,仅从内存中的程序集生成元数据引用的问题不再存在,因为Core 1.0中不再存在这些引用,因此每个程序集都具有Location属性.因此,获取这些引用基本上与ASP.net 4中的过程相同: MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName(assemblyName)).Location); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |