lima-city: Webhosting, Domains und Cloud
1 Pluspunkt 0 Minuspunkte

Ich habe eine Klasse, die ganz normal kompiliert im Projekt liegt. Jetzt würde ich gerne C# Code aus einer externen Datei (z. B. einer .cs oder .txt Datei) einlesen, zur Laufzeit kompilieren und dieser Code soll dann die vorhandene - bereits kompilierte - Klasse erweitern oder von ihr erben.

Laut diesem Blog ist das mit dem Paket Microsoft.CodeAnalysis.CSharp technisch machbar, wie würde man das in der Praxis umsetzen?

von  

1 Antwort

0 Pluspunkte 0 Minuspunkte

Das kannst du z.B mit Roslyn. Erstelle ein neues C# Projekt und füge eine Referenz zum Paket Microsoft.CodeAnalysis.CSharp hinzu.

using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

public interface IPlugin
{
    void Execute();
}

class Program
{
    static async Task Main()
    {

        string code = await File.ReadAllTextAsync("Plugin.cs");
        var syntaxTree = CSharpSyntaxTree.ParseText(code);
        var references = AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic && !string.IsNullOrWhiteSpace(a.Location)).Select(a => MetadataReference.CreateFromFile(a.Location)).Cast<MetadataReference>();
        var compilation = CSharpCompilation.Create("DynamicAssembly", new[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

        using var ms = new MemoryStream();
        var result = compilation.Emit(ms);

        if (!result.Success)
        {
            foreach (var diagnostic in result.Diagnostics)
                Console.WriteLine(diagnostic);
            return;
        }

        ms.Seek(0, SeekOrigin.Begin);
        var assembly = Assembly.Load(ms.ToArray());
        var type = assembly.GetTypes().FirstOrDefault(t => typeof(IPlugin).IsAssignableFrom(t));
        if (type != null)
        {
            var plugin = (IPlugin)Activator.CreateInstance(type);
            plugin.Execute();
        }
    }
}

In den Ordner, in dem das kompilierte Programm (die Exe Datei) liegt, legst du die Datei Plugin.cs.

public class HelloPlugin : IPlugin
{
    public void Execute()
    {
        System.Console.WriteLine("Hello world from dynamic plugin!");
    }
}

Wenn du die Exe Datei ausführst sollte "Hello world from dynamic plugin!" ausgegeben werden.

von (1.3k Punkte)