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
C# Skript zur Laufzeit laden und Methode aus Skript aufrufen
Wax
myCSharp.de - Member

Avatar #avatar-2276.jpg


Dabei seit:
Beiträge: 745
Herkunft: Dortmund

Themenstarter:

C# Skript zur Laufzeit laden und Methode aus Skript aufrufen

beantworten | zitieren | melden

Guten Tag,

ich schaue mich gerade nach einer Möglichkeit um, mit der ich zur Laufzeit ein externes C#-Skript (liegt im Dateisystem in einem zugreifbaren Ordner) laden und Methoden innerhalb dieses Skripts ausführen kann.

Also z.B. würde das Skript folgende Methode enthalten, die ich gerne zur Laufzeit aufrufen würde:


public Task<object> Execute(object parameter) {}

Nun finde ich Beiträge im Netz von 2010, in denen z.B. der Typ Microsoft.CSharp.CSharpCodeProvider verwendet wird um den Code zu laden und on-thy-fly zu kompilieren.

Ist es aktuell immer noch der Weg den man gehen sollte oder hat sich in der Zwischenzeit da etwas getan und ich würde auf das falsche, schlecht gealterte, Pferd setzen? Vielleicht gibt es inzwischen bessere (Standard-) Bibliotheken?

Gruß
private Nachricht | Beiträge des Benutzers
Wax
myCSharp.de - Member

Avatar #avatar-2276.jpg


Dabei seit:
Beiträge: 745
Herkunft: Dortmund

Themenstarter:

beantworten | zitieren | melden

Ich muss wohl etwas weiter ausholen merke ich gerade....

Innerhalb des Skripts, sollen andere Entwickler ihren C# Code ausführen können, der wiederum auf andere 3rd Party Bibliotheken zurückgreifen muss.

Jetzt habe ich Ansätze wie die Roslyn Scripting API gesehen, die Code Zeile für Zeile ausführt.
Dadurch würden zur Laufzeit ja nicht automatisch die benötigten 3rd Party Assemblies geladen werden oder etwa doch?

Muss ich vielleicht doch lieber eine Assembly per AssemblyResolver als Plug-in laden und aufrufen anstatt ein Skript zu laden?

Die Skript Variante erschien mir Anfangs attraktiv, da so die anderen Entwickler für Anpassungen nicht immer erst eine Plug-in DLL kompilieren müssten, sondern den Skript-Code "mal eben" anpassen und sofort laufen lassen könnten.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Wax am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16152

beantworten | zitieren | melden

Die .NET Runtime bietet an für sich keine Scripting-Schnittstellen an.

Alle vorhandenen "Aufsätze" mit solch einem Vorhaben sind aktuell Workarounds; alle mit Limits. Ein vollständiges "C# Plugin System" mit 1:1 üblichem C# Code ist derzeit nicht möglich.

Es gibt zB die CS Script Engine; aber auch diese hat Limitations bzgl. Dependencies und Co (zB Assemblies, NuGet und Co).
Zitat von Wax
Dadurch würden zur Laufzeit ja nicht automatisch die benötigten 3rd Party Assemblies geladen werden oder etwa doch?
Natürlich nicht. Auch Rosyln kann nicht hellsehen.
Du musst alles deklarieren, was Abhängigkeiten sind. Das passiert eigentlich implizit durch Deine Entwicklungsbumgebung; aber wenn Du selbst direkt mit der Schnittstelle sprichst musst Du das alles komplett selbst machen.
Zitat von Wax
Die Skript Variante erschien mir Anfangs attraktiv, da so die anderen Entwickler für Anpassungen nicht immer erst eine Plug-in DLL kompilieren müssten, sondern den Skript-Code "mal eben" anpassen und sofort laufen lassen könnten.
Und genau dafür ist .NET nicht konzipiert und im Endeffekt sind genau solche Anwendungen eher instabil.

Es gibt zwar .NET Interactive; aber das bietet derzeit keine Möglichkeit irgendeinen Kontext (aka sowas wie eine App Domain) zu injizieren.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
david.m
myCSharp.de - Member



Dabei seit:
Beiträge: 116

beantworten | zitieren | melden

Wenn man Spaß hat, kann man auch sein eigenes System bauen.
Dazu kann man sich ja mal .Cake (C# Make) ansehen.
private Nachricht | Beiträge des Benutzers
JimStark
myCSharp.de - Member

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 293

beantworten | zitieren | melden

Zitat von Wax
Die Skript Variante erschien mir Anfangs attraktiv, da so die anderen Entwickler für Anpassungen nicht immer erst eine Plug-in DLL kompilieren müssten, sondern den Skript-Code "mal eben" anpassen und sofort laufen lassen könnten.

Zumindest bei .NET Core ist es doch auch kein großes rumgetue mehr mit dem CLI.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16152

beantworten | zitieren | melden

Jim, und wie soll die CLI die Anforderung von Wax mit Scripting erfüllen?
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
JimStark
myCSharp.de - Member

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 293

beantworten | zitieren | melden

Siehe Zitat. Wenn ich mir ein Shellskript für den Buildaufruf schreibe ist es so gut wie kein Mehraufwand gegenüber dem bloßen Editieren der cs Datei mehr.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16152

beantworten | zitieren | melden

Versetz Dich mal in die Lage einer Nicht-Dev Umgebung, die solche Anforderungen oft haben:

Für ne CLI brauche ich ein SDK - für das Editieren einer CS-Datei einen Texteditor, das direkt selbst in der Anwendung gemacht werden könnte.
Das sind schon riesige Unterschiede.

Genau für solche Anforderungen verwenden viele oft immer noch VB-Script.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Wax
myCSharp.de - Member

Avatar #avatar-2276.jpg


Dabei seit:
Beiträge: 745
Herkunft: Dortmund

Themenstarter:

beantworten | zitieren | melden

Danke für die bisherigen Antworten!

@Abt: Bisher wurden diese Probleme tatsächlich mit VB-Script gelöst. Da gab es keine Assemblies die in App-Domains geladen werden und OOP bis ans Limit.

Da das Kernprodukt in C# entwickelt wurde und die meisten Entwickler innerhalb der Firma auch C# beherrschen, wollte man am liebsten in dieser Sprache bleiben.

Vielleicht ist der Ansatz aber auch einfach verkehrt. Ich versuche das ursprüngliche Problem mal zu schildern...

Innerhalb des C# Codes gibt es Stellen die, falls eine Implementierung für diese Stelle/Hook existiert, diese Implementierung dann auch durchlaufen werden soll. Quasi nach dem Motto: Wurde ein Handler für diesen Hook gefunden, dann rufe ihn auf und lass ihn arbeiten. Die Signaturen dieser "Erweiterungspunkte" wären wohl definiert und die Entwickler würden sich an die Konventionen halten und somit könnte die Hauptanwendung die Methode innerhalb des "Erweiterungsskriptes" finden und aufrufen. Leider sind diese "Erweiterungsskripte", wie immer, abhängig von anderen Assemblies.

Von daher sehe ich inzwischen eigentlich nur noch die Plug-in Lösung. Also die Entwickler sollen bitte sehr DLLs in nen bestimmten Ordner werfen und die Hauptanwendung scannt diese Ordner nach verwendbaren Modulen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Wax am .
private Nachricht | Beiträge des Benutzers
Wax
myCSharp.de - Member

Avatar #avatar-2276.jpg


Dabei seit:
Beiträge: 745
Herkunft: Dortmund

Themenstarter:

beantworten | zitieren | melden

Ich bin soeben über "CS-Script" gestolpert.
Das könnte mich schon ein ganzes Stück weiter bringen, wenn es hält was es verspricht.

Ich muss mir das mal anschauen...
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1520
Herkunft: Düsseldorf

beantworten | zitieren | melden

Zitat
Von daher sehe ich inzwischen eigentlich nur noch die Plug-in Lösung. Also die Entwickler sollen bitte sehr DLLs in nen bestimmten Ordner werfen und die Hauptanwendung scannt diese Ordner nach verwendbaren Modulen.

Was spricht denn dagegen?
Wenn's mal schnell gehen soll, kann man ja auch direkt mit VS bauen und die DLL hin legen, das dauert nicht lange und hat außerdem noch sämtliche Unterstützungen, die VS zu bieten hat.

Wo ist denn der Nachteil, das so zu machen?

Ein Script (egal welche Sprache) würde ich nur dann verwenden, wenn der Anwender selber damit arbeiten können möchte, oder wir aus irgendeinem anderen Grund, nicht dafür verantwortlich sind.
Ein Script für uns intern ... ne danke, dann doch lieber Visual Studio (Code) :D

Außerdem hat man damit langfristig mehr Möglichkeiten, auch im Bezug auf neue Versionen und Abwärtskompatibilität.
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



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

beantworten | zitieren | melden

Klingt für mich auch erstmal mehr nach einem Plugin System auf .NET Basis als ein sinnvoller Ansatz für Skript Einbindungen jedweder Art.
Aber um sicher zu gehen, hättest du den Beispiele wie der aktuelle Ansatz bei euch im Code aussieht/umgesetzt wird?

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
Wax
myCSharp.de - Member

Avatar #avatar-2276.jpg


Dabei seit:
Beiträge: 745
Herkunft: Dortmund

Themenstarter:

beantworten | zitieren | melden

@T-Virus: Aktuell wäre der Plan, zur Laufzeit an einer bestimmten Stelle im Code nach [BestimmterOrdner]\[BestimmterDateiname].cs zu suchen. Falls diese Datei existiert, sollte ein ScriptingHost die Datei laden und eine gewünschte (hoffentlich vorhandene Methode) ausführen.

Der Kunde könnte im Endeffekt selbst Hand anlegen und z.B. hauseigene Bibliotheken zur Ver-/Entschlüsselung von Inhalten zwischen schalten.

Das mit dem Scripting ist nur aufgekommen, da das Produktmanagement meint, es wäre für die Kunden bzw. unsere Consultants einfacher mal eben in einer kundenspezifischen Programmierung ein Skript anzupassen, anstatt eine DLL zu kompilieren.

Ich selbst bin ein Freund der Plug-in Lösung. Allerdings kann ich auch die Einfachheit der Skript-Lösung nachvollziehen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Wax am .
private Nachricht | Beiträge des Benutzers
BerndFfm
myCSharp.de - Team

Avatar #nZo9Gyth4VPDSxGqM4sT.jpg


Dabei seit:
Beiträge: 3783
Herkunft: Frankfurt a.M.

beantworten | zitieren | melden

Ich mache das so, speichere den Sourcecode aber in der Datenbank in einer Textspalte.

Die Anwender können sich selber Scripts in C# oder Visual Basic schreiben und an bestimmten Stellen ausführen lassen.

Dazu gibt es verschiedene Vorlagen für verschiedene Zwecke.

Grüße Bernd
Attachments
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
private Nachricht | Beiträge des Benutzers
Wax
myCSharp.de - Member

Avatar #avatar-2276.jpg


Dabei seit:
Beiträge: 745
Herkunft: Dortmund

Themenstarter:

beantworten | zitieren | melden

@BerndFfm: Mit welchem "Scripting-Host" werden die Skripte denn geladen bzw. ausgeführt und unterstützt du das Laden von 3rd Party Libraries (durch Referenzen auf die Assemblies) oder muss sich das Skript da selbst drum kümmern?
private Nachricht | Beiträge des Benutzers
BerndFfm
myCSharp.de - Team

Avatar #nZo9Gyth4VPDSxGqM4sT.jpg


Dabei seit:
Beiträge: 3783
Herkunft: Frankfurt a.M.

beantworten | zitieren | melden

Ich benutze den eingebauten Compiler.

Assemblies muss man alle hinzufügen, das muss man selber machen.

Man kann angeblich auch VB, F#, Javascript und C++ übersetzen und ausführen, klappt bei mir aber noch nicht alles.

CSharpCodeProvider codeProvider = new CSharpCodeProvider(new Dictionary<String, String> { { "CompilerVersion", "v3.5" } });
ICodeCompiler icc = codeProvider.CreateCompiler();
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add("System.dll");
...
parameters.GenerateInMemory = true;
parameters.GenerateExecutable = true;
parameters.IncludeDebugInformation = false;
CompilerResults results = icc.CompileAssemblyFromSource(parameters, source);
if (results.Errors.Count > 0) ...
...
MethodInfo main = null;
Object[] args = null;
main = program.GetMethod("ListeAusgeben");
args = new Object[] { qdb, ds };
main.Invoke(null, args);

Grüße Bernd

PS.: CreateCompiler() sollte nicht mehr benutzt werden.
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16152

beantworten | zitieren | melden

Nur als Hinweis, der Vollständigkeit halber:
Das kompiliert mit der alten .NET Welt; die neue .NET Welt verwendet Roslyn.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers