Visual Studio 2019, 16.9.4
Microsoft.CodeAnalysis.CSharp 3.9.0
Ich möchte Dapper ORM-Mappings dynamisch erstellen und verwende dazu folgenden Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using DFM = Dapper.FluentMap.Mapping;
namespace Fips.ORM.Dapper
{
public class MappersCreator
{
private Type CreateType(Type type, string name, Dictionary<string,string> mappings)
{
var assemblyName = type.Assembly.FullName;
var nspace = type.Namespace;
var sb = new StringBuilder();
foreach (var kv in mappings) {
sb.Append($" Map(m => m.{kv.Key}).ToColumn(\"{kv.Value}\");\n");
}
var code = $@"using Dapper.FluentMap.Mapping;
namespace {nspace}
{{
public class {name}Mapper : EntityMap<{name}>
{{
public {name}Mapper()
{{
{sb.ToString()}
}}
}}
}}";
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
new[] { syntaxTree },
new MetadataReference[] {
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(type.Assembly.Location),
MetadataReference.CreateFromFile(typeof(DFM.EntityMap<Type>).Assembly.Location),
MetadataReference.CreateFromFile(typeof(Expression<Type>).Assembly.Location),
MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location),
},
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);
using (var memoryStream = new MemoryStream()) {
EmitResult result = compilation.Emit(memoryStream);
if (result.Success) {
memoryStream.Seek(0, SeekOrigin.Begin);
Assembly assembly = Assembly.Load(memoryStream.ToArray());
Type ret = assembly.GetType($"{nspace}.{name}");
return ret;
} else {
foreach (var diagnostic in result.Diagnostics) {
Console.WriteLine(diagnostic);
}
return null;
}
}
}
}
}
Leider kriege ich nur folgende Fehler bei compilation.Emit(memoryStream) auf Zeile 51:
Fehler
(5,32): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(9,13): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(9,13): error CS0012: The type 'Expression<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(9,30): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(10,13): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(10,13): error CS0012: The type 'Expression<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(10,33): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
Klingt für mich eher nach einem Fall für ein eigenes Snippet.
Warum machst du es dir hier schwer und willst mit Roslyn was generieren lassen, was Code Snippets in VS schon erledigen können?
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
Der Typ soll natürlich zur Laufzeit generiert werden, generierter Source oder gar eine Installation von VS kann ich nicht voraussetzen.
Im Prinzip hätt ich auch per System.Reflection.Emit.GetILGenerator direkt Bytecode erzeugen können, aber das ist mir zu hoch!
Leider hat das auch keinen Einfluss. Das CLI ist (natürlich) netcoreapp3.1, aber der ganze Rest netstandard2.0.
Könntest du dir das kurz anschauen? So wie ich mich kenne, liegt es an was ganz Blödem...
BTW: ich dachte es ist ein Roslyn Source Generator. Sind dir diese bekannt? Damit kann zur Entwurfszeit Code erstellt werden und verweidet dies zur Laufzeit -- sofern möglich.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Vielen Dank für deine Unterstützung!
Es geht mir nicht um das CodeGenerator-Projekt, sondern um ORM.Test.
Die Solution kompiliert bei mir auch, aber wenn ich das ORM.Test-Projekt ausführe, kommen diese Fehler:
Fehler
(5,32): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(9,13): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(9,13): error CS0012: The type 'Expression<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(9,30): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(10,13): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(10,13): error CS0012: The type 'Expression<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
(10,33): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
Klappt das bei dir?
Ich möchte wie gesagt auch keinen Source generieren, sondern fertige Typen.
Ich stecke wieder fest, und zwar erhalte ich beim Compiliern der Mapper folgende Fehler (Projekt Fipscode.ORM.Test):
Fehler
(9,49): error CS0234: The type or namespace name 'SloganMapper' does not exist in the namespace 'Fipscode.ORM.Dapper.Fipscode.Entities.Test' (are you missing an assembly reference?)
(10,13): error CS0012: The type 'User' is defined in an assembly that is not referenced. You must add a reference to assembly 'Fipscode.Entities.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Könntet ihr euch das vielleicht nochmal ansehen?
Der zu kompilierende Sourcecode wird auch ausgegeben, zum besseren Verständnis.