Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Roslyn: CSharpCompilation.Emit missachtet Referenzen
Fabiano
myCSharp.de - Member



Dabei seit:
Beiträge: 25

Themenstarter:

Roslyn: CSharpCompilation.Emit missachtet Referenzen

beantworten | zitieren | melden

Hallo Leute!

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'.

Das ist mein CSPROJ-File:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Dapper" Version="2.0.78" />
    <PackageReference Include="Dapper.FluentMap" Version="2.0.0" />
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
  </ItemGroup>

  <ItemGroup>
    <Reference Include="System.Linq" />
    <Reference Include="System.Linq.Expressions" />
    <Reference Include="netstandard" />
  </ItemGroup>
</Project>

Warum werden meine Referenzenangaben auf den Zeilen 42 und 45 (scheinbar) einfach ignoriert? Oder was ist sonst der Fehler?

Liebe Grüsse,
Fabiano
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Experte



Dabei seit:
Beiträge: 2.117
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Fabiano
myCSharp.de - Member



Dabei seit:
Beiträge: 25

Themenstarter:

beantworten | zitieren | melden

Vielen Dank für deine schnelle Antwort!

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!
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 6.865
Herkunft: Waidring

beantworten | zitieren | melden

Hallo Fabiano,

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

</Project>

Hat mich auch schon ein paar Nerven gekostet, aber es geht (momentan) nur mit .NET Standard 2.0 als TFM.

Edit: dazu gibt es eine Issue Don't limit Source Generators to "netstandard2.0" target framework · Issue #45162 · dotnet/roslyn

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!"
private Nachricht | Beiträge des Benutzers
Fabiano
myCSharp.de - Member



Dabei seit:
Beiträge: 25

Themenstarter:

beantworten | zitieren | melden

Vielen Dank für deine Antwort!

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...

Gruss,
Fabiano
Attachments
private Nachricht | Beiträge des Benutzers
gfoidl
myCSharp.de - Team

Avatar #avatar-2894.jpg


Dabei seit:
Beiträge: 6.865
Herkunft: Waidring

beantworten | zitieren | melden

Hallo Fabiano,

die Solution kompiliert bei mir wenn ich in Fipscode.CodeGenerator.csproj diie Referenzen hinzufüge:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="System.CodeDom" Version="5.0.0" />
        <PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
    </ItemGroup>

</Project>

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!"
private Nachricht | Beiträge des Benutzers
jogibear9988
myCSharp.de - Member



Dabei seit:
Beiträge: 638
Herkunft: Offenau

beantworten | zitieren | melden

Ich denke mein problem war ähnlich. Vlt. hilgft der Issue dazu weiter: https://github.com/dotnet/roslyn/issues/50612
cSharp Projekte : https://github.com/jogibear9988
private Nachricht | Beiträge des Benutzers
Fabiano
myCSharp.de - Member



Dabei seit:
Beiträge: 25

Themenstarter:

beantworten | zitieren | melden

Hallo gfoidl

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.

Gruss,
Fabiano
private Nachricht | Beiträge des Benutzers
Fabiano
myCSharp.de - Member



Dabei seit:
Beiträge: 25

Themenstarter:

beantworten | zitieren | melden

Hallo jogibear9988

Diese 2 Zeilen von dir haben meinen Tag gerettet! Ach was, die ganze Woche!

                MetadataReference.CreateFromFile(Assembly.Load("netstandard").Location),
                MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location)

Nochmals vielen Dank euch beiden, dass ihr euch gekümmert habt! Einen wunderschönen Abend!

Gruss,
Fabiano
private Nachricht | Beiträge des Benutzers
Fabiano
myCSharp.de - Member



Dabei seit:
Beiträge: 25

Themenstarter:

beantworten | zitieren | melden

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.
Attachments
private Nachricht | Beiträge des Benutzers