私は、動的に作成されたクラスの集合体を持っていますので、個別にコンパイルしたい(そしてコンパイルエラーを修正したい)。次に、それらを同じアセンブリに結合したいと思います。それらはすでにコンパイルされているので、(2回コンパイルするのを避けるために)構文木をアセンブリコンパイルに渡すだけではいけません。 それらをネットモジュールにコンパイルしようとしていたが、それらのネットモジュールをアセンブリへの参照として使用しようとしましたが、結果のアセンブリに必要な型がありません。ここでRoslynを使ってクラスを別々にコンパイルし、それらをアセンブリで一緒に組み合わせる
は、それがAとBへの参照を見つけることができないので(ロスリンのCompilationEmitTests.MultipleNetmodulesWithPrivateImplementationDetailsに非常によく似())私のテストコード
public static class Program
{
public static void Main()
{
var s1 = @"public class A {internal object o1 = new { hello = 1, world = 2 }; public static string M1() { return ""Hello, "";}}";
var s2 = @"public class B : A{internal object o2 = new { hello = 1, world = 2 };public static string M2(){ return ""world!"";}}";
var s3 = @"public class Program{public static void Main(){ System.Console.Write(A.M1()); System.Console.WriteLine(B.M2());}}";
var comp1 = CreateCompilationWithMscorlib("a1", s1, compilerOptions: TestOptions.ReleaseModule);
var ref1 = comp1.EmitToImageReference();
var comp2 = CreateCompilationWithMscorlib("a2", s2, compilerOptions: TestOptions.ReleaseModule, references: new[] { ref1 });
var ref2 = comp2.EmitToImageReference();
var comp3 = CreateCompilationWithMscorlib("a3", s3, compilerOptions: TestOptions.ReleaseExe.WithModuleName("C"), references: new[] { ref1, ref2 });
var ref3 = comp3.EmitToImageReference();
IEnumerable<byte> result = comp3.EmitToArray();
Assembly assembly = Assembly.Load(result.ToArray());
Module module = assembly.GetModule("C");
Type prog = module.GetType("Program");
object instance = Activator.CreateInstance(prog);
MethodInfo method = prog.GetMethod("Main");
method.Invoke(null, null);
}
public static ImmutableArray<byte> ToImmutable(this MemoryStream stream)
{
return ImmutableArray.Create<byte>(stream.ToArray());
}
internal static ImmutableArray<byte> EmitToArray
(
this Compilation compilation,
EmitOptions options = null,
Stream pdbStream = null
)
{
var stream = new MemoryStream();
if (pdbStream == null && compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
{
pdbStream = new MemoryStream();
}
var emitResult = compilation.Emit(
peStream: stream,
pdbStream: pdbStream,
xmlDocumentationStream: null,
win32Resources: null,
manifestResources: null,
options: options);
return stream.ToImmutable();
}
public static MetadataReference EmitToImageReference(
this Compilation comp
)
{
var image = comp.EmitToArray();
if (comp.Options.OutputKind == OutputKind.NetModule)
{
return ModuleMetadata.CreateFromImage(image).GetReference(display: comp.AssemblyName);
}
else
{
return AssemblyMetadata.CreateFromImage(image).GetReference(display: comp.AssemblyName);
}
}
private static CSharpCompilation CreateCompilationWithMscorlib(string assemblyName, string code, CSharpCompilationOptions compilerOptions = null, IEnumerable<MetadataReference> references = null)
{
SourceText sourceText = SourceText.From(code, Encoding.UTF8);
SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(sourceText, null, "");
MetadataReference mscoreLibReference = AssemblyMetadata.CreateFromFile(typeof(string).Assembly.Location).GetReference();
IEnumerable<MetadataReference> allReferences = new MetadataReference[] { mscoreLibReference };
if (references != null)
{
allReferences = allReferences.Concat(references);
}
CSharpCompilation compilation = CSharpCompilation.Create
(
assemblyName,
new[] {syntaxTree},
options : compilerOptions,
references: allReferences
);
return compilation;
}
}
メインは()静的メソッドを呼び出し()で例外がスローされていますクラス。
私は間違っていますか?
スタックトレースをドロップすると役立つでしょう。 – muglio
ダイナミックプログラム(文字列s3で定義)は、AとB(文字列s1とs2で定義されたネットモジュールにある)への参照を見つけることができません。ロザリン特有のものは何もありません。 –
誰かが興味を持っている人は、こちらのソリューションをご覧ください:https://github.com/dotnet/roslyn/issues/11297。 – svick