Roslyn-создание MetadataReference из сборки в памяти
работа над ASP.NET 5 приложение (Visual Studio 2015 CTP5) и Microsoft.CodeAnalysis.Используется CSharp.
Если я попытаюсь создать MetadataReference для сборки, которая является частью решения, чтобы передать ее как ссылку на CSharpCompilation.Создаю, получаю систему.Исключение ArgumentException, "пустое имя пути не допускается".
// Throws exception
MetadataReference.CreateFromAssembly(typeof(this).Assembly);
// Doesn't throw exception
MetadataReference.CreateFromAssembly(typeof(Object).Assembly);
Если я проверяю свойство Location сборки, оно пусто. Я предполагаю, что это связано с новым способом составления заявок в памяти в ASP.NET 5, так что сборка не хранится на диске.
Итак, есть ли способ передать ссылку на Roslyn для сборки без свойства Location или это в настоящее время не поддерживается?
изменить: @JaredPar - @SLaks выделил точно, где он терпит неудачу, но вот полная трассировка стека для информации. Я создаю несколько других MetadataReferences из System.* сборки до этого и нет никаких проблем ни с одной из них.
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, FileMode mode, FileAccess access, 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()
2 ответов
прошло некоторое время, но я получил ответ на этот вопрос в репозитории GitHub Roslyn, поэтому я опубликую его, если кто-то найдет этот вопрос:
ASP.NET 5 имеет API для этого. Ты можешь делать то, что делает бритва.https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNet.Mvc.Razor/Compilation/RoslynCompilationService.cs#L132
Это было в районе Beta1 Asp.Net 5 поэтому может потребоваться настройка, но принцип все тот же-следуйте API, который Asp.Net сам по себе использует через IAssemblyLoadContextAccessor
которое инжектор обслуживания обеспечит.
спасибо Дэвиду Фаулеру
UPDATE: этот ответ был для ASP.NET 5 Beta1. API сильно изменился, и в Core 1.0 вместо использования IAssemblyLoadContextAccessor вы можете получить доступ к AssemblyLoadContext из статического члена:
System.Runtime.Loader.AssemblyLoadContext.Default
и затем вы можете вызвать LoadFromStream для загрузки сборки из двоичного изображения. Вот очень грубый набросок кода, который я использую с некоторыми ненужными битами, взломанными out:
// 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);
Ваш вопрос неясен.
Если у вас есть байты скомпилированной сборки в памяти, вызовите MetadataReference.CreateFromImage()
.
Если вы хотите добавить ссылку на проект Roslyn в той же рабочей области, вызовите Compilation.ToMetadataReference()
.