C# Roslyn 编译 - 在动态编译代码中使用 Nuget 包 - 编译但在运行时抛出异常(无法加载文件或程序集)
C# Roslyn Compile - Use Nuget Package within dynamically compiled Code - compiles but throws an Exception at runtime (Could not load file or assembly)
我尝试使用 Roslyn 编译器在动态编译代码中使用 Nuget 包来完成。
我想在我的代码中使用 Nuget 包(在我的示例 https://www.nuget.org/packages/TinyCsvParser/ 中)。于是我下载了压缩包解压到一个文件夹(C:\Data\packages\tinycsvparser.2.6.1)
但我不希望它成为我的应用程序的直接依赖项。所以它没有在项目本身中引用,我不想将它复制到 bin/Debug-Folder.
Nuget-Package-DLL 应该可以在我的硬盘上的任何地方。
编译运行没有任何错误。但是在 method.Invoke(fooInstance, null) 行的运行时我得到以下异常:
Could not load file or assembly 'TinyCsvParser, Version=2.6.1.0, Culture=neutral, PublicKeyToken=d7df35b038077099' or one of its dependencies. The system cannot find the file specified.
如何告诉程序应该在哪里寻找 DLL?
我用下面的行试了一下
Assembly nugetAssembly = Assembly.LoadFrom(pathToNugetDLL);
但这并没有帮助。
感谢您提供有关如何解决此问题的任何建议。
这是我的代码(原型):
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text;
namespace Playground
{
public static class Program
{
private const string pathToNugetDLL = @"C:\Data\packages\tinycsvparser.2.6.1\lib\net45\TinyCsvParser.dll";
private const string firstClass =
@"
using TinyCsvParser;
namespace A
{
public class MyClass
{
public int MyFunction()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, ';');
return 1;
}
}
}";
public static void Main()
{
CSharpParseOptions parseOptions = new CSharpParseOptions(LanguageVersion.CSharp7, DocumentationMode.Parse, SourceCodeKind.Regular);
SyntaxTree parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(firstClass, parseOptions);
List<string> defaultNamespaces = new List<string>() { };
//// Referenzen über Kommentare heraussuchen:
List<MetadataReference> defaultReferences = CreateMetadataReferences();
var encoding = Encoding.UTF8;
var assemblyName = Path.GetRandomFileName();
var symbolsName = Path.ChangeExtension(assemblyName, "pdb");
var sourceCodePath = "generated.cs";
var buffer = encoding.GetBytes(firstClass);
var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);
var syntaxTree = CSharpSyntaxTree.ParseText(
sourceText,
new CSharpParseOptions(),
path: sourceCodePath);
var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode;
var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding);
CSharpCompilationOptions defaultCompilationOptions =
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Debug).WithPlatform(Platform.AnyCpu)
.WithUsings(defaultNamespaces);
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { encoded },
references: defaultReferences,
options: defaultCompilationOptions
);
using (var assemblyStream = new MemoryStream())
using (var symbolsStream = new MemoryStream())
{
var emitOptions = new EmitOptions(
debugInformationFormat: DebugInformationFormat.Pdb,
pdbFilePath: symbolsName);
var embeddedTexts = new List<EmbeddedText> { EmbeddedText.FromSource(sourceCodePath, sourceText) };
EmitResult result = compilation.Emit(
peStream: assemblyStream,
pdbStream: symbolsStream,
embeddedTexts: embeddedTexts,
options: emitOptions);
if (result.Success)
{
Console.WriteLine("Complation succeeded!");
try
{
Assembly nugetAssembly = Assembly.LoadFrom(pathToNugetDLL);
var assembly = Assembly.Load(assemblyStream.ToArray(), symbolsStream.ToArray());
var type = assembly.GetType("A.MyClass");
MethodInfo method = type.GetMethod("MyFunction");
var fooInstance = Activator.CreateInstance(type);
method.Invoke(fooInstance, null);
}
catch (Exception ex)
{
int i = 0;
}
}
}
}
private static List<MetadataReference> CreateMetadataReferences()
{
string defaultPath = typeof(object).Assembly.Location.Replace("mscorlib", "{0}");
var metadatenReferences = new List<MetadataReference>()
{
MetadataReference.CreateFromFile(string.Format(defaultPath, "mscorlib")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Data")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Core")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.ComponentModel.DataAnnotations")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Xml")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "netstandard")),
};
string strExtraDll = pathToNugetDLL;
metadatenReferences.Add(MetadataReference.CreateFromFile(strExtraDll));
return metadatenReferences;
}
}
}
我可以使用事件处理程序解决问题
AppDomain.CurrentDomain.AssemblyResolve
有了它我可以解决依赖关系。
这里是原型代码的最终结果:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
namespace Playground
{
public static class Program
{
public static void Main()
{
var test = new Test();
test.TestMethod();
}
}
public class Test
{
private const string pathToNugetDLL = @"C:\Data\packages\tinycsvparser.2.6.1\lib\net45\TinyCsvParser.dll";
private const string firstClass =
@"
using TinyCsvParser;
namespace A
{
public class MyClass
{
public int MyFunction()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, ';');
return 1;
}
}
}";
public void TestMethod()
{
CSharpParseOptions parseOptions = new CSharpParseOptions(LanguageVersion.CSharp7, DocumentationMode.Parse, SourceCodeKind.Regular);
SyntaxTree parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(firstClass, parseOptions);
List<string> defaultNamespaces = new List<string>() { };
//// Referenzen über Kommentare heraussuchen:
List<MetadataReference> defaultReferences = CreateMetadataReferences();
var encoding = Encoding.UTF8;
var assemblyName = Path.GetRandomFileName();
var symbolsName = Path.ChangeExtension(assemblyName, "pdb");
var sourceCodePath = "generated.cs";
var buffer = encoding.GetBytes(firstClass);
var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);
var syntaxTree = CSharpSyntaxTree.ParseText(
sourceText,
new CSharpParseOptions(),
path: sourceCodePath);
var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode;
var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding);
CSharpCompilationOptions defaultCompilationOptions =
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Debug).WithPlatform(Platform.AnyCpu)
.WithUsings(defaultNamespaces);
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { encoded },
references: defaultReferences,
options: defaultCompilationOptions
);
using (var assemblyStream = new MemoryStream())
using (var symbolsStream = new MemoryStream())
{
var emitOptions = new EmitOptions(
debugInformationFormat: DebugInformationFormat.Pdb,
pdbFilePath: symbolsName);
var embeddedTexts = new List<EmbeddedText> { EmbeddedText.FromSource(sourceCodePath, sourceText) };
EmitResult result = compilation.Emit(
peStream: assemblyStream,
pdbStream: symbolsStream,
embeddedTexts: embeddedTexts,
options: emitOptions);
if (result.Success)
{
Console.WriteLine("Complation succeeded!");
try
{
AppDomain.CurrentDomain.AssemblyResolve += AppDomain_AssemblyResolve;
Assembly nugetAssembly = Assembly.LoadFrom(pathToNugetDLL);
var assembly = Assembly.Load(assemblyStream.ToArray(), symbolsStream.ToArray());
var type = assembly.GetType("A.MyClass");
MethodInfo method = type.GetMethod("MyFunction");
var fooInstance = Activator.CreateInstance(type);
method.Invoke(fooInstance, null);
}
catch (Exception ex)
{
int i = 0;
}
finally
{
AppDomain.CurrentDomain.AssemblyResolve -= AppDomain_AssemblyResolve;
}
}
}
}
private Assembly AppDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string[] assemblyInfoSplitted = args.Name.Split(',');
string strSearchedForAssemblyName = assemblyInfoSplitted[0];
var fileInfo = new FileInfo(pathToNugetDLL);
var strAssemblyName = Regex.Replace(fileInfo.Name, ".dll", "", RegexOptions.IgnoreCase);
if (strSearchedForAssemblyName.ToLower() == strAssemblyName.ToLower())
{
//File.ReadAllBytes because DLL might be deleted afterwards in the filesystem
return Assembly.Load(File.ReadAllBytes(pathToNugetDLL));
}
throw new Exception($"Could not resolve Assembly '{strSearchedForAssemblyName}'.");
}
private static List<MetadataReference> CreateMetadataReferences()
{
string defaultPath = typeof(object).Assembly.Location.Replace("mscorlib", "{0}");
var metadatenReferences = new List<MetadataReference>()
{
MetadataReference.CreateFromFile(string.Format(defaultPath, "mscorlib")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Data")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Core")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.ComponentModel.DataAnnotations")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Xml")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "netstandard")),
};
string strExtraDll = pathToNugetDLL;
metadatenReferences.Add(MetadataReference.CreateFromFile(strExtraDll));
return metadatenReferences;
}
}
}
这里有 2 个问题:
- 正在编译
- 运行
试试这个:
public class Test
{
private const string firstClass =
@"
using TinyCsvParser;
namespace A
{
public class MyClass
{
public int MyFunction()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, ';');
return 1;
}
}
}";
public void TestMethod()
{
var parseOptions = new CSharpParseOptions(LanguageVersion.CSharp7, DocumentationMode.Parse, SourceCodeKind.Regular);
var parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(firstClass, parseOptions);
var defaultReferences = CreateMetadataReferences();
var encoding = Encoding.UTF8;
var assemblyName = Path.GetRandomFileName();
var symbolsName = Path.ChangeExtension(assemblyName, "pdb");
var sourceCodePath = "generated.cs";
var buffer = encoding.GetBytes(firstClass);
var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);
var syntaxTree = CSharpSyntaxTree.ParseText(
sourceText,
new CSharpParseOptions(),
path: sourceCodePath);
var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode;
var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding);
CSharpCompilationOptions defaultCompilationOptions =
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithOverflowChecks(true)
.WithOptimizationLevel(OptimizationLevel.Debug)
.WithPlatform(Platform.AnyCpu);
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { encoded },
references: defaultReferences,
options: defaultCompilationOptions
);
using var assemblyStream = new MemoryStream();
using var symbolsStream = new MemoryStream();
var emitOptions = new EmitOptions(
debugInformationFormat: DebugInformationFormat.Pdb,
pdbFilePath: symbolsName);
var embeddedTexts = new List<EmbeddedText> { EmbeddedText.FromSource(sourceCodePath, sourceText) };
EmitResult result = compilation.Emit(
peStream: assemblyStream,
pdbStream: symbolsStream,
embeddedTexts: embeddedTexts,
options: emitOptions);
if (result.Success)
{
Console.WriteLine("Complation succeeded!");
try
{
var assembly = Assembly.Load(assemblyStream.ToArray(), symbolsStream.ToArray());
var type = assembly.GetType("A.MyClass");
MethodInfo method = type.GetMethod("MyFunction");
var fooInstance = Activator.CreateInstance(type);
method.Invoke(fooInstance, null);
Console.WriteLine("Invocation succeeded!");
}
catch (Exception ex)
{
Console.WriteLine($"Invocation failed!\n{ex}");
}
}
else
{
Console.WriteLine("Complation failed!");
foreach (var diagnostic in result.Diagnostics)
{
Console.WriteLine(diagnostic.ToString());
}
}
}
private static IEnumerable<MetadataReference> CreateMetadataReferences()
{
var tinyCsvParserAssembly = typeof(TinyCsvParser.CsvParserOptions).Assembly;
var metadatenReferences = new Dictionary<string, MetadataReference>();
GetReferenecedAssemblies(metadatenReferences, tinyCsvParserAssembly);
return metadatenReferences.Values;
static void GetReferenecedAssemblies(Dictionary<string, MetadataReference> references, Assembly assembly)
{
var assemblyName = assembly.FullName;
if (!references.ContainsKey(assemblyName))
{
references.Add(assemblyName, MetadataReference.CreateFromFile(assembly.Location));
foreach (var referencedAssembly in assembly.GetReferencedAssemblies())
{
GetReferenecedAssemblies(references, Assembly.Load(referencedAssembly));
}
}
}
}
}
我尝试使用 Roslyn 编译器在动态编译代码中使用 Nuget 包来完成。
我想在我的代码中使用 Nuget 包(在我的示例 https://www.nuget.org/packages/TinyCsvParser/ 中)。于是我下载了压缩包解压到一个文件夹(C:\Data\packages\tinycsvparser.2.6.1)
但我不希望它成为我的应用程序的直接依赖项。所以它没有在项目本身中引用,我不想将它复制到 bin/Debug-Folder.
Nuget-Package-DLL 应该可以在我的硬盘上的任何地方。
编译运行没有任何错误。但是在 method.Invoke(fooInstance, null) 行的运行时我得到以下异常:
Could not load file or assembly 'TinyCsvParser, Version=2.6.1.0, Culture=neutral, PublicKeyToken=d7df35b038077099' or one of its dependencies. The system cannot find the file specified.
如何告诉程序应该在哪里寻找 DLL? 我用下面的行试了一下
Assembly nugetAssembly = Assembly.LoadFrom(pathToNugetDLL);
但这并没有帮助。
感谢您提供有关如何解决此问题的任何建议。
这是我的代码(原型):
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text;
namespace Playground
{
public static class Program
{
private const string pathToNugetDLL = @"C:\Data\packages\tinycsvparser.2.6.1\lib\net45\TinyCsvParser.dll";
private const string firstClass =
@"
using TinyCsvParser;
namespace A
{
public class MyClass
{
public int MyFunction()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, ';');
return 1;
}
}
}";
public static void Main()
{
CSharpParseOptions parseOptions = new CSharpParseOptions(LanguageVersion.CSharp7, DocumentationMode.Parse, SourceCodeKind.Regular);
SyntaxTree parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(firstClass, parseOptions);
List<string> defaultNamespaces = new List<string>() { };
//// Referenzen über Kommentare heraussuchen:
List<MetadataReference> defaultReferences = CreateMetadataReferences();
var encoding = Encoding.UTF8;
var assemblyName = Path.GetRandomFileName();
var symbolsName = Path.ChangeExtension(assemblyName, "pdb");
var sourceCodePath = "generated.cs";
var buffer = encoding.GetBytes(firstClass);
var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);
var syntaxTree = CSharpSyntaxTree.ParseText(
sourceText,
new CSharpParseOptions(),
path: sourceCodePath);
var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode;
var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding);
CSharpCompilationOptions defaultCompilationOptions =
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Debug).WithPlatform(Platform.AnyCpu)
.WithUsings(defaultNamespaces);
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { encoded },
references: defaultReferences,
options: defaultCompilationOptions
);
using (var assemblyStream = new MemoryStream())
using (var symbolsStream = new MemoryStream())
{
var emitOptions = new EmitOptions(
debugInformationFormat: DebugInformationFormat.Pdb,
pdbFilePath: symbolsName);
var embeddedTexts = new List<EmbeddedText> { EmbeddedText.FromSource(sourceCodePath, sourceText) };
EmitResult result = compilation.Emit(
peStream: assemblyStream,
pdbStream: symbolsStream,
embeddedTexts: embeddedTexts,
options: emitOptions);
if (result.Success)
{
Console.WriteLine("Complation succeeded!");
try
{
Assembly nugetAssembly = Assembly.LoadFrom(pathToNugetDLL);
var assembly = Assembly.Load(assemblyStream.ToArray(), symbolsStream.ToArray());
var type = assembly.GetType("A.MyClass");
MethodInfo method = type.GetMethod("MyFunction");
var fooInstance = Activator.CreateInstance(type);
method.Invoke(fooInstance, null);
}
catch (Exception ex)
{
int i = 0;
}
}
}
}
private static List<MetadataReference> CreateMetadataReferences()
{
string defaultPath = typeof(object).Assembly.Location.Replace("mscorlib", "{0}");
var metadatenReferences = new List<MetadataReference>()
{
MetadataReference.CreateFromFile(string.Format(defaultPath, "mscorlib")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Data")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Core")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.ComponentModel.DataAnnotations")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Xml")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "netstandard")),
};
string strExtraDll = pathToNugetDLL;
metadatenReferences.Add(MetadataReference.CreateFromFile(strExtraDll));
return metadatenReferences;
}
}
}
我可以使用事件处理程序解决问题
AppDomain.CurrentDomain.AssemblyResolve
有了它我可以解决依赖关系。
这里是原型代码的最终结果:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
namespace Playground
{
public static class Program
{
public static void Main()
{
var test = new Test();
test.TestMethod();
}
}
public class Test
{
private const string pathToNugetDLL = @"C:\Data\packages\tinycsvparser.2.6.1\lib\net45\TinyCsvParser.dll";
private const string firstClass =
@"
using TinyCsvParser;
namespace A
{
public class MyClass
{
public int MyFunction()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, ';');
return 1;
}
}
}";
public void TestMethod()
{
CSharpParseOptions parseOptions = new CSharpParseOptions(LanguageVersion.CSharp7, DocumentationMode.Parse, SourceCodeKind.Regular);
SyntaxTree parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(firstClass, parseOptions);
List<string> defaultNamespaces = new List<string>() { };
//// Referenzen über Kommentare heraussuchen:
List<MetadataReference> defaultReferences = CreateMetadataReferences();
var encoding = Encoding.UTF8;
var assemblyName = Path.GetRandomFileName();
var symbolsName = Path.ChangeExtension(assemblyName, "pdb");
var sourceCodePath = "generated.cs";
var buffer = encoding.GetBytes(firstClass);
var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);
var syntaxTree = CSharpSyntaxTree.ParseText(
sourceText,
new CSharpParseOptions(),
path: sourceCodePath);
var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode;
var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding);
CSharpCompilationOptions defaultCompilationOptions =
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Debug).WithPlatform(Platform.AnyCpu)
.WithUsings(defaultNamespaces);
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { encoded },
references: defaultReferences,
options: defaultCompilationOptions
);
using (var assemblyStream = new MemoryStream())
using (var symbolsStream = new MemoryStream())
{
var emitOptions = new EmitOptions(
debugInformationFormat: DebugInformationFormat.Pdb,
pdbFilePath: symbolsName);
var embeddedTexts = new List<EmbeddedText> { EmbeddedText.FromSource(sourceCodePath, sourceText) };
EmitResult result = compilation.Emit(
peStream: assemblyStream,
pdbStream: symbolsStream,
embeddedTexts: embeddedTexts,
options: emitOptions);
if (result.Success)
{
Console.WriteLine("Complation succeeded!");
try
{
AppDomain.CurrentDomain.AssemblyResolve += AppDomain_AssemblyResolve;
Assembly nugetAssembly = Assembly.LoadFrom(pathToNugetDLL);
var assembly = Assembly.Load(assemblyStream.ToArray(), symbolsStream.ToArray());
var type = assembly.GetType("A.MyClass");
MethodInfo method = type.GetMethod("MyFunction");
var fooInstance = Activator.CreateInstance(type);
method.Invoke(fooInstance, null);
}
catch (Exception ex)
{
int i = 0;
}
finally
{
AppDomain.CurrentDomain.AssemblyResolve -= AppDomain_AssemblyResolve;
}
}
}
}
private Assembly AppDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string[] assemblyInfoSplitted = args.Name.Split(',');
string strSearchedForAssemblyName = assemblyInfoSplitted[0];
var fileInfo = new FileInfo(pathToNugetDLL);
var strAssemblyName = Regex.Replace(fileInfo.Name, ".dll", "", RegexOptions.IgnoreCase);
if (strSearchedForAssemblyName.ToLower() == strAssemblyName.ToLower())
{
//File.ReadAllBytes because DLL might be deleted afterwards in the filesystem
return Assembly.Load(File.ReadAllBytes(pathToNugetDLL));
}
throw new Exception($"Could not resolve Assembly '{strSearchedForAssemblyName}'.");
}
private static List<MetadataReference> CreateMetadataReferences()
{
string defaultPath = typeof(object).Assembly.Location.Replace("mscorlib", "{0}");
var metadatenReferences = new List<MetadataReference>()
{
MetadataReference.CreateFromFile(string.Format(defaultPath, "mscorlib")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Data")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Core")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.ComponentModel.DataAnnotations")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "System.Xml")),
MetadataReference.CreateFromFile(string.Format(defaultPath, "netstandard")),
};
string strExtraDll = pathToNugetDLL;
metadatenReferences.Add(MetadataReference.CreateFromFile(strExtraDll));
return metadatenReferences;
}
}
}
这里有 2 个问题:
- 正在编译
- 运行
试试这个:
public class Test
{
private const string firstClass =
@"
using TinyCsvParser;
namespace A
{
public class MyClass
{
public int MyFunction()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, ';');
return 1;
}
}
}";
public void TestMethod()
{
var parseOptions = new CSharpParseOptions(LanguageVersion.CSharp7, DocumentationMode.Parse, SourceCodeKind.Regular);
var parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(firstClass, parseOptions);
var defaultReferences = CreateMetadataReferences();
var encoding = Encoding.UTF8;
var assemblyName = Path.GetRandomFileName();
var symbolsName = Path.ChangeExtension(assemblyName, "pdb");
var sourceCodePath = "generated.cs";
var buffer = encoding.GetBytes(firstClass);
var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);
var syntaxTree = CSharpSyntaxTree.ParseText(
sourceText,
new CSharpParseOptions(),
path: sourceCodePath);
var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode;
var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding);
CSharpCompilationOptions defaultCompilationOptions =
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithOverflowChecks(true)
.WithOptimizationLevel(OptimizationLevel.Debug)
.WithPlatform(Platform.AnyCpu);
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { encoded },
references: defaultReferences,
options: defaultCompilationOptions
);
using var assemblyStream = new MemoryStream();
using var symbolsStream = new MemoryStream();
var emitOptions = new EmitOptions(
debugInformationFormat: DebugInformationFormat.Pdb,
pdbFilePath: symbolsName);
var embeddedTexts = new List<EmbeddedText> { EmbeddedText.FromSource(sourceCodePath, sourceText) };
EmitResult result = compilation.Emit(
peStream: assemblyStream,
pdbStream: symbolsStream,
embeddedTexts: embeddedTexts,
options: emitOptions);
if (result.Success)
{
Console.WriteLine("Complation succeeded!");
try
{
var assembly = Assembly.Load(assemblyStream.ToArray(), symbolsStream.ToArray());
var type = assembly.GetType("A.MyClass");
MethodInfo method = type.GetMethod("MyFunction");
var fooInstance = Activator.CreateInstance(type);
method.Invoke(fooInstance, null);
Console.WriteLine("Invocation succeeded!");
}
catch (Exception ex)
{
Console.WriteLine($"Invocation failed!\n{ex}");
}
}
else
{
Console.WriteLine("Complation failed!");
foreach (var diagnostic in result.Diagnostics)
{
Console.WriteLine(diagnostic.ToString());
}
}
}
private static IEnumerable<MetadataReference> CreateMetadataReferences()
{
var tinyCsvParserAssembly = typeof(TinyCsvParser.CsvParserOptions).Assembly;
var metadatenReferences = new Dictionary<string, MetadataReference>();
GetReferenecedAssemblies(metadatenReferences, tinyCsvParserAssembly);
return metadatenReferences.Values;
static void GetReferenecedAssemblies(Dictionary<string, MetadataReference> references, Assembly assembly)
{
var assemblyName = assembly.FullName;
if (!references.ContainsKey(assemblyName))
{
references.Add(assemblyName, MetadataReference.CreateFromFile(assembly.Location));
foreach (var referencedAssembly in assembly.GetReferencedAssemblies())
{
GetReferenecedAssemblies(references, Assembly.Load(referencedAssembly));
}
}
}
}
}