compiladores de c#
¿Cómo compilar un archivo C#con Roslyn programáticamente? (2)
Leí que no se puede compilar C # 6.0 con CSharpCodeProvider y, por lo tanto, tratar de hacerlo con Roslyn. Pero no puedo encontrar un buen ejemplo de cómo cargar un archivo y luego compilarlo en un dll.
¿Cómo debo escribir algo similar a este código con Roslyn? ¿O hay alguna otra manera de hacerlo? Ahora, cuando intento compilar archivos que contienen referencias a proyectos con código C # 6.0, simplemente diga "El tipo o nombre de espacio de nombres ''x'' no existe en el espacio de nombres ''y'' (¿falta una referencia de ensamblado?)"
public string CompileCode()
{
var provider = new CSharpCodeProvider();
var outputPath = Path.Combine(Path.GetDirectoryName(_path), $"Code.dll");
var compilerparams = new CompilerParameters(_referencedAssemblies, outputPath);
CompilerResults results = provider.CompileAssemblyFromFile(compilerparams, _path);
var dllPath = results.PathToAssembly;
if (!results.Errors.HasErrors)
return dllPath;
PrintError(results.Errors);
return "";
}
En resumen quiero:
- Cargar un archivo de C #
- Compílalo en un dll para poder cargarlo más tarde.
He creado una muestra para que trabajes. Debe ajustarlo para usar el tiempo de ejecución de .Net 4.6, de modo que la versión CSharp6 esté disponible para usted. He añadido pequeños detalles para que pueda elegir las opciones de compilaciones.
Cambios requeridos: cambie la ruta del tiempo de ejecución a target .Net 4.6 Cambie LanguageVersion.Csharp5
a LanguageVersion.Csharp6
en la siguiente muestra.
class Program
{
private static readonly IEnumerable<string> DefaultNamespaces =
new[]
{
"System",
"System.IO",
"System.Net",
"System.Linq",
"System.Text",
"System.Text.RegularExpressions",
"System.Collections.Generic"
};
private static string runtimePath = @"C:/Program Files (x86)/Reference Assemblies/Microsoft/Framework/.NETFramework/v4.5.1/{0}.dll";
private static readonly IEnumerable<MetadataReference> DefaultReferences =
new[]
{
MetadataReference.CreateFromFile(string.Format(runtimePath, "mscorlib")),
MetadataReference.CreateFromFile(string.Format(runtimePath, "System")),
MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Core"))
};
private static readonly CSharpCompilationOptions DefaultCompilationOptions =
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Release)
.WithUsings(DefaultNamespaces);
public static SyntaxTree Parse(string text, string filename = "", CSharpParseOptions options = null)
{
var stringText = SourceText.From(text, Encoding.UTF8);
return SyntaxFactory.ParseSyntaxTree(stringText, options, filename);
}
static void Main(string[] args)
{
var fileToCompile = @"C:/Users/DesktopHome/Documents/Visual Studio 2013/Projects/ConsoleForEverything/SignalR_Everything/Program.cs";
var source = File.ReadAllText(fileToCompile);
var parsedSyntaxTree = Parse(source, "", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp5));
var compilation
= CSharpCompilation.Create("Test.dll", new SyntaxTree[] { parsedSyntaxTree }, DefaultReferences, DefaultCompilationOptions);
try
{
var result = compilation.Emit(@"c:/temp/Test.dll");
Console.WriteLine(result.Success ? "Sucess!!" : "Failed");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.Read();
}
Esto necesitaría pequeños ajustes pero debería darle los resultados deseados. Cámbiala como quieras.
Tienes que usar el paquete NuGet Microsoft.CodeAnalysis.CSharp
.
var syntaxTree = CSharpSyntaxTree.ParseText(source);
CSharpCompilation compilation = CSharpCompilation.Create(
"assemblyName",
new[] { syntaxTree },
new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) },
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var dllStream = new MemoryStream())
using (var pdbStream = new MemoryStream())
{
var emitResult = compilation.Emit(dllStream, pdbStream);
if (!emitResult.Success)
{
// emitResult.Diagnostics
}
}