Autor Beitrag
Arakis
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Do 16.11.06 22:10 
Hi, nach 2 Jahren mal wieder ein Beitrag von mir in diesen Forum ;)

Ich habe einen Script-Kompilierer/-Interperter in .NET geschrieben, um Scripte in einer speziellen Sprache auszuführen, ohne dass dabei temporäre Assemblies den Speicher zumüllen.

Damit kann man z.B. eigene Programme anpassbar gestalten. Ich habe das Projekt erst seit heute online, vielleicht möchte sich dass ja mal jemand ansehen:

scripting.larne.de

Dokumentation gibt es leider keine :/
Bin für jedes Feedback dankbar.
Einloggen, um Attachments anzusehen!
_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!


Zuletzt bearbeitet von Arakis am Mo 20.11.06 15:53, insgesamt 3-mal bearbeitet
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Do 16.11.06 22:32 
Hallo!

Vom Beispiel-Skript her sieht die Sprache schon mal recht mächtig aus. Mir gefällt vor allem, dass man .NET-Klassen verwenden kann.

Um ein paar Tests zu erleichtern, wäre aber eine Kurz-Doku der wichtigsten Klassen, die man verwendet, nicht schlecht. :-)

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Fr 17.11.06 10:04 
Hallo Christian,
Klassen, welche man wo verwendet? Um die Script-Engine zum Laufen zu bringen(aus Sicht der Host-Anwendung), oder welche es in der Script-Engine gibt?

Zu ersterem gibt es keine Doku, und zu letzterem die Klassenreferenz vom .NET Framework ;) Denn es kommt ganz darauf an was man der Script-Engine gibt. Um weitere Assemblys in der Script-Engine zu registrieren, braucht man nur die Init.ls anpassen:

ausblenden Quelltext
1:
2:
3:
4:
WriteLine('Initialisierung...');
LoadAssembly('mscorlib.dll');
LoadAssembly('System.dll');
WriteLine('Fertig.');


Zu beachten ist, dass die Script-Engine keine Namespaces oder geschachtelte Typen kennt. Wenn z.B. System.IO.File registriert wird und MyProject.File, dann gewinnt ersteres.

Auch zu beachten ist, dass die Funktkion LoadAssembly nur in der Init.ls aufgerufen wird.

Wenn man eine Sandbox erstellen möchte, dann läd man schreibt man den ScriptHost(LarneScript.exe, Projekt liegt bei) etwas um, wirft die Funktion LoadAssembly raus und registriert schon im Host jede Klasse manuell, z.b. nur grundlegende .NET Datentypen und die zu automatisierenden Objekte seines eigenen Programmes.

Ich verwende die Script-Engine z.b. in meinem Internetspiel, damit die Spieler ihren Account "Scripten" können(Sandbox) und in einem Softwareprodukt, welches ich zur Zeit für eine Firma entwickel(Anpassbarkeit von Logiken).

Gruß,
Sebastian

_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 17.11.06 10:43 
user profile iconArakis hat folgendes geschrieben:
Um die Script-Engine zum Laufen zu bringen(aus Sicht der Host-Anwendung), oder welche es in der Script-Engine gibt?
Die, um die Script-Engine zum Laufen zu bringen.

user profile iconArakis hat folgendes geschrieben:
Zu ersterem gibt es keine Doku,
Das schränkt die Nutzbarkeit Deines Projektes leider sehr ein.

Ich hätte es gerne mal getestet, aber mittels Reflector und des Beispielprojekts selber zusammen zu suchen, wie ich das Teil benutze ist ... äh ... suboptimal ;-)

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Fr 17.11.06 12:42 
Du hast recht, das werde ich die Tage dann mal machen. Wobei es da eigentlich nicht viel zu dokumentieren gibt, selbst ich verwende in meinem Internetspiel nur wenige Funktionen, um die Script-Engine zum laufen zu bekommen.

Hier ein Beispiel mit Quelltextkommentaren:

ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
Public Shared Sub InitScriptEngine()
  'Registriert bei der Script-Engine eingei Must-Have-Datentypen und Funktionen, wie Wertetypen und die Methode WriteLine
  ScriptLib.Init()

  'Registriert einen eigenen Datentypen
  ScriptLib.AddScriptObject(GetType(TMyTestObject))

  'Wollen wir auch globale Methoden hinzufügen, so müssen dieser als Shared markiert sein
  ScriptLib.AddScriptObject(GetType(TMyGlobalScriptMethods))

  'Hiermit wird der Script-Engine mitgeteilt, dass sie diese Typen nach globalen Methoden durchsuchen soll.
  'Dieser Funktion könnte noch etwas vereinfacht werden, in dem sie nur noch den Typ als System.Type erwartet
  ScriptLib.AddStaticMethodType(ScriptLib.GetScriptObjectClass("TMyGlobalScriptMethods"))

  'Ganz wichtig: ScriptLib.InitParams()! Damit werden bei allen registrierten Typen die Parameter ausgelesen und mit vorhandenen
  'registrierten Datentypen in Verbindung gebracht, damit zur Laufzeit fast keine Listen mehr abgefragt werden müssen.
  ScriptLib.InitParams()
End Sub

Friend Shared Function ExecuteScript(ByVal Source As String) As Boolean
  'TCodeCompiler ist nur eine Hilfsklasse um bequem die Tokens zu generieren, Variablen zu deklarieren und den Code zu generieren.
  Dim Compiler As New TCodeCompiler()

  'Tokens sind die kleinste Logische Quelltexteinheit, wie z.b. Literals, Schlüsselwörter etc.
  'Somit brauchen bei der Kompilierung keine String-Operationen mehr durchgeführt werden
  Dim Tokens() As TCodeToken = Compiler.GetTokens(Source)

  'Zur Kompilierung als auch zur Laufzeit wird eine Output-Klasse benötigt, in der alle Meldungen wandern.
  'Bei bedarf einfach von TScriptOutput erben und die Funktion "InternalWrite" überschreiben.
  Dim Output As New TScriptOutputConsole

  'Generiert aus den Tokens nun einen ausführbaren Code(für den Interperter bzw. ScriptContext)
  Dim Code As TScriptCode = Compiler.CreateCode(Tokens, Output)

  'Bei fehlgeschlagener Kompilierung kann das Script nicht gestartet werden
  If Compiler.HasError Then
    Console.WriteLine("Kompilierung fehlgeschlagen")
    Return False
  End If

  'Erzeugen vom Script-Kontext bzw. des "Interperters", welche den Code ausführt.
  Dim Context As New TScriptContext(Code, Output)

  'Die Init-Methode kopiert die deklarierten Variabeln vom Code in einen neuen, lokalen Variabel-Speicher
  Context.Init()

  'Zeit in Milisekunden, wie lange das Script maximal laufen darf. 0=Endlos.
  Context.ScriptTimeout = 0

  'Führt das Script aus.
  Context.Execute()

  Return True
End Function

Public Class TScriptOutputConsole
  Inherits TScriptOutput

  Protected Overrides Sub InternalWrite(ByVal msg As String)
    Console.Write(msg)
  End Sub

End Class


Ich hoffe das das "etwas" weiterhilft ;)

_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 17.11.06 16:21 
Ah ja, das hat geholfen. Eine Frage habe ich. Ich habe diesen Quelltext:
ausblenden volle Höhe Chrome-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
namespace LarneTest;

interface

uses
  enobis.utils.Scripting.*;

type
  ConsoleApp = class
  public
    class method Main;
  end;
  
  ScriptOutputConsole = class(TScriptOutput)
  protected
    method InternalWrite(msg : String); override;
  end;
  
  MyTestObject = class
  private
  public
    property MyVal : String;
  end;


implementation

class method ConsoleApp.Main;
begin
  ScriptLib.Init;
  ScriptLib.AddScriptObject(typeof(MyTestObject));  
  ScriptLib.InitParams;
  
  var source := 'Var myObj as New MyTestObject();'+
                'myObj.MyVal = ''foo'';'+
                'WriteLine(myObj.MyVal);';
  
  var compiler := new TCodeCompiler;
  var tokens := compiler.GetTokens(source);
  var output := new ScriptOutputConsole;
  var code := compiler.CreateCode(tokens, output);
  
  if code.HasError then
  begin
    Console.WriteLine('Fehler!');
    Console.Readline;   
    exit;  
  end;
  
  var context := new TScriptContext(code, output);
  context.Init;
  context.ScriptTimeout := 0;
  context.Execute;
  Console.ReadLine;
end;

method ScriptOutputConsole.InternalWrite(msg : String); 
begin
  Console.Write(msg);
end;

end.


Wie könnte ich jetzt in einer Methode der Klasse MyTestObject z.B. auf WriteLine zugreifen?

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Fr 17.11.06 17:16 
Hi, ich verstehe jetzt nicht ganz was du meinst. .NET Objekte, welche du in der Script-Engine registrierst, haben Voll-Zugriff auf alles, halt ganz normale .NET Programmierung. Die Script-Engine kann dieser Objekte nun von "außen" erzeugen, und damit arbeiten. Wenn du nun in deinem Objekt ausgaben machen möchtest, so kannst du dies einfach über Console.WriteLine lösen.

Anmerkung: die globale Methode "WriteLine" ist ein sonderfall. Sie ist speziell "hardgecoded" damit immer gewährleistet wird, dass das Script was ausgeben kann. WriteLine schreibt letzten endes alles in TScriptContext.Output rein, welches bei der Instanzierung von TScriptContext übergeben wurde. Somit kann man z.B. Schreibvorgänge umleiten.

Um es noch einmal zusammenzufassen:
Man kann in .NET Klassen schreiben wie man möchte, mit der vollen Mächtigkeit von .NET. Wie die Klassen was machen, ist halt dem .NET Programmierer überlassen. Das ist die Seite von .NET.

Dann gibt es die Seite des Scripts. Das kann auf die .NET Objekte zugrifen, sofern dieser Registriert wurden. Es kann dieser Instanzieren, dessen Methodenaufrufen etc.

Scripte können also auf .NET-Objekte zugrifen, nicht jedoch umgekehrt.

Noch ein Hinweis: Man kann in der Script-Engine keine eigenen Klassen definieren.

_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 17.11.06 17:52 
user profile iconArakis hat folgendes geschrieben:
Hi, ich verstehe jetzt nicht ganz was du meinst. .NET Objekte, welche du in der Script-Engine registrierst, haben Voll-Zugriff auf alles, halt ganz normale .NET Programmierung.
Aber ich registriere doch nur Klassen und keine Objekte. Die Objekte (Instanzen) muss ich ja im Skript erzeugen. Und diese im Skript erzeugten Instanzen haben keinen Zugriff auf Dinge außerhalb des Skripts, oder?

Damit stellt dann die Methode WriteLine doch die einzige Möglichkeit dar, mit der Außenwelt zu "kommunizieren". Ob das nun eine Anzeige in der Konsole ist oder eine Anzeige als MessageBox oder in einem Label. Es wäre also praktisch, wenn ich in einem Objekt auf diese Methode zugreifen könnte.

Ich stelle mir das so vor, dass Du einen Delegate erstellst, der so aussieht:
ausblenden Delphi-Quelltext
1:
type myDelegate = method InternalWrite(msg : String);					


Dann könnte man die WriteLine-Methode als Parameter an Objekte im Skript übergeben:

ausblenden Skript
1:
2:
3:
Var myObj as New MyTestObject();
myObj.MyVal = 'foo';
myObj.DoOutput(myDelegate(WriteLine));


Und DoOutput sähe dann so aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
  MyTestObject = class
  private
  public
    property MyVal : String;
    method DoOuptut(outMethod : myDelegate);
  end;

{...}
method MyTestObject.DoOuptut(outMethod : myDelegate);
begin
  outMethod(myVal);
end;


Verstehst Du, was ich meine? Damit hätten alle in der Engine registrierten Klassen Zugriff auf die WriteLine-Methode.

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Fr 17.11.06 18:12 
Hallo Sebastian,
natürlich hat das Script mehrere Möglichkeiten mit der Außenwelt zu kommunizieren. Hier ein Beispiel:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
Public Class TMyClass

  Public Function GetFileSize(ByVal Path As String) As Integer
    Return New IO.FileInfo(Path).Length
  End Function

  Public Sub QuitHost()
    Environment.Exit(0)
  End Sub

  Public Function GetWebPage(ByVal url As String) As String
    Dim wc As New Net.WebClient
    Try
      Return System.Text.Encoding.Default.GetString(wc.DownloadData(url))
    Finally
      wc.Dispose()
    End Try
  End Function

End Class

ScriptLib.AddScriptObject(GetType(TMyClass))


ausblenden Quelltext
1:
2:
3:
4:
var obj as new TMyClass();
WriteLine(obj.GetWebPage('http://www.google.de'));
WriteLine(obj.GetFileSize('C:\boot.ini'));
obj.QuitHost(); // :-P


Was du nun möchest ist, dass ein .NET Objekt auf die WriteLine-Methode zugreifen kann - Das ist so ohne weiteres gar nicht möglich. Und Delegates werden zur Zeit nicht unterstützt. Wenn die Output-Methode aber shared ist und in der Host-Global definiert ist, dann kann ja jedes .NET Objekt darauf zugreifen. Es gäbe aber einen sauberen WorkArround:

eine globale, shared Varibable "CurrentScriptContext" vom Typ TScriptContext mit dem Attribute ThreadStatic. Wenn bevor execute aufgerufen wird, der Variabel die Context-Instanz zuweisen. .NET objekte machen dann folgendes:

CurrentScriptContext.Output.WriteLine(...);

_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 17.11.06 18:25 
Hm. Ich fände da eine Möglichkeit schön, auf Objekte (Instanzen) zuzugreifen, die außerhalb des Skriptes liegen (also z.B. ein Label oder eine Form oder so). Könnte man es einrichten, dass man nicht nur Klassen, sondern auch Instanzen registrieren kann? Das würde sicherlich vieles vereinfachen und irgendwelche Work-Arounds überflüssig machen.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Fr 17.11.06 19:13 
Du kannst einem Script vor Ausführung Variablen übergeben:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
'Label-Klasse registrieren
ScriptLib.AddScriptObject(GetType(Label))

'Lokale Script-Variabel vor der Kompilierung vor-definieren
Dim Compiler As TCodeCompiler
'{...}
Compiler.DefinedVariables.Declare("MyLabel", GetType(Label))

'Lokale Script-Variabel setzen
Dim Context As TScriptContext
'{...}
Context.Init()
Context.GlobalVarStorage.Set("MyLabel", MyForm.Label1, Context.Output)


So kann dann darauf zugegriffen werden:
ausblenden Quelltext
1:
MyLabel.Text = 'huhu';					


Es bestünde auch die Möglichkeit, ein .NET Objekt zu schreiben mit einer Methode GetMyObject() welche das Script nachträglich mit Daten versorgt.

_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Fr 17.11.06 19:19 
Ah, schick! Dann kann ich ja mal ein bisschen weiter spielen :-)

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Mo 20.11.06 14:16 
Hier ist ein kleines Update. Funktional wurde nichts verändert, nur habe ich nun Script-Engine aus der enobis.utils.dll rausgetrennt, ist sinnvoller, denn schließlich haben haben DB- und Html-tools nix in der Script-Engine zu suchen. Desweiteren wurden die Klassen in sinnvolle Namespaces gepackt.

Bei Gelegenheit muss ich auch mal ein paar Funktionen sinnvoll umbenennen, denn z.b. AddScriptObject müsste besser heißen "RegisterScriptType". Aber alles nach und nach ;-)

Was macht die "Spielerei"? Gibt es Fragen?

Ein nice to have Feature wären bei Gelegenheit noch Optionale Parameter und Automatische Parameter Arrays. Aber ist ne Menge Arbeit, werde ich daher erstmal nicht machen(das "unstrenge" binding an überladene Methoden bereitet so schon genug Probleme in manchen Situationen).

Ach ja, und ein Switch müsste noch rein. Zu den Delegates: Wäre eine Überlegung wert dies einzubauen, ist auch recht gut umsetzbar. Nur eins wird bleiben: Die ScriptEngine wird schnittstellen nach außen haben, jedoch ist für externe Objekte die Script-engine eine art black box, es können keine selbst definierten methoden von außen aufgerufen werden. wobei das eigentlcih ganz nett wäre, muss mir nur ncoh im klaren werden wie man dies am besten umsetzt.

Und ncoh ein schmeißen von Fehlermeldungen per Script, das dürfte der kleinste aufwand werden. Ein Try-catch-finally ist leider nicht möglich, weil alles "flach" abgearbeitet wird und das ein compiler-feature ist vom nativen .net. Aber vielleicht fällt mir da doch noch was ein, z.b. ein TCodeCatchExceptionExpression, welches ein anderes umschließt, welches eine Exception einfach abfängt. Aber das wäre dann auf Expression-Ebene und nciht auf Code-Line(-Command)-Ebene.

Grüße,
Sebastian
Einloggen, um Attachments anzusehen!
_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Mo 20.11.06 17:49 
Habe nu noch ein paar Dinge umbenannt und was veraltetes rausgeschmissen. Mit dieser Version dürfte die Script-Engine in Zukunft auch einibermaßen abwärtskompatibel sein.

Script-Methdoe "Zufallszahl" ist rausgeflogen, so wie auch die Klasse "TClass1".

ScriptLib.InitParams --> ScriptLib.InitParameters
ScriptLib.AddScriptObject --> ScriptLib.RegisterType
ScriptLib.AddStaticMethodType --> ScriptLib.RegisterGlobalMethodType

Das wars erstmal. Über ein wenig Feedback würde ich mich sehr freuen.

Grüße,
Sebastian
Einloggen, um Attachments anzusehen!
_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Mo 20.11.06 20:52 
Hallo!

Ich finde Deine Skriptengine wirklich sehr schick :zustimm:

Eine Frage habe ich noch:
ausblenden Delphi-Quelltext
1:
  ScriptLib.RegisterType(typeof(List<String>));					


Wie kann ich jetzt im Skript diesen Typen verwenden?

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Di 21.11.06 10:04 
Wahrscheinlich gar nicht, da die Script-Engine zur Zeit keine generischen Klassen unterstützt - muss sie meiner Meinung im ersten Step nicht, wäre einfach nur ein Nice-to-Have Feature. Das weitere Problem ist, dass es erstmal mit .NET 1.1 kompatibel sein muss, vor allem da ich die Script-engine zur Zeit noch in meinem Internetspiel verwende, welches aus unerklärlichen Gründen bei .NET 2.0 nach einigen Minuten im IIS abstürtzt ohne Fehlermelung ohne Eregnismprotokolleintrag, ohne alles.

Aber um dennoch ganz ehrlich zu sein: Ich habe noch nie mit generischen Klassen gearbeitet *g*

Grüße,
Sebastian

_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Di 21.11.06 10:38 
user profile iconArakis hat folgendes geschrieben:
Wahrscheinlich gar nicht, da die Script-Engine zur Zeit keine generischen Klassen unterstützt
Ich übergebe ihr ja aber nicht den offenen Typ List<>, sondern einen konstruierten Typ List<String>. Der ist ja eigentlich nicht mehr generisch.

user profile iconArakis hat folgendes geschrieben:
Aber um dennoch ganz ehrlich zu sein: Ich habe noch nie mit generischen Klassen gearbeitet *g*
Da hast Du was verpasst ;-)

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Di 21.11.06 10:51 
Was vielleicht auch ein ganz nettes Projekt wäre, ist, eine Reihe von sinnvollen Open-Source-Assemblies mit vereinfachten Wrappern für die Script-engine als Bundle zusammenzustellen, um das Kommendozeilentool LarneScript.exe mit weiteren Funktionen auszustatten. So wäre das eine gute Batch-Alternative --> .LS-Dateien mit der LarneScript.exe assoziieren, im BIN-Ordner eine config.dnl anlegen und dann gehts ab - z.b. brauch ich ein bei Gelegenheit ein Script, welches mir Dateien von einem FTP-Server löscht - Wenn sinnvolle/vereinfachte Wrapper vorhanden sind, dann kann man auch per Script solche "komplexen" Aufgaben lösen.

_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Arakis Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 344



BeitragVerfasst: Mi 29.11.06 11:19 
Hallo Christian,
hast du noch ein wenig getestet?

Gruß,
Sebastian

_________________
Mit dem Computer löst man Probleme, die man ohne ihn nicht hätte.
Entwickler von SpaceTrek: The New Empire - Siehe Hompage!
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Do 30.11.06 17:37 
Hallo!

Ich habe über folgendes nachgedacht: Nehmen wir an, ich schreibe eine Klasse mit einem gewissen Funktionsumfang. Nun möchte ich, dass der volle Funktionsumfang im richtigen Programm zur Verfügung steht, im Skript aber nur ein Teil davon. Das könnte man ansich ganz gut über ein Interface machen.

Dieses Interface legt die Methoden und Properties fest, welche im Skript vorhanden sein sollen. Die Klasse implementiert dieses Interface und hat dann noch ein paar mehr Methoden. Das sind dann die Methoden, die nur im eigentlichen Programm aber nicht im Skript zur Verfügung stehen.

Dem Skript mache ich als Typ dann nur das Interface bekannt, nicht die "richtige" Klasse. Damit kann man im Skript nur auf die Methoden und Properties des Interfaces zugreifen.

Leider scheinen Interfaces nicht unterstützt zu werden, sehe ich das richtig? Hatte das so versucht:

ausblenden Chrome-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  SomeInterface = interface
    property foo : String read write;
    
  end;
  
  SomeClass = class(SomeInterface)
  private
  public    
    method DoSomething;
    property foo : String;
  end;

ausblenden Chrome-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
  ScriptLib.Init;
  ScriptLib.RegisterType(typeof(SomeInterface));
  ScriptLib.InitParameters;
  
  var source := textBox1.Text;  
  var compiler := new TCodeCompiler;
  
  var aSomeClass := new SomeClass;
  compiler.DefinedVariables.Declare('ASomeClass', typeof(SomeInterface));  
  
  var tokens := compiler.GetTokens(source);
  var output := new ScriptOutputConsole;
  output.aTextBox := textBox2;
  var code := compiler.CreateCode(tokens, output);
  
  if code.HasError then
  begin
    MessageBox.Show('Fehler!');    
    exit;  
  end;
  
  var context := new TScriptContext(code, output);
  context.Init;
  context.ScriptTimeout := 0;
  context.GlobalVarStorage.Set('ASomeClass', aSomeClass, context.Output);
  context.Execute;

Hier wäre dann nur die Property "foo" im Skript verfügbar, die Methode DoSomething aber nicht. Leider scheitert bereits ein Skript wie dieses:
ausblenden Quelltext
1:
ASomeClass.foo := 'bar';					

mit der Meldung
Zitat:
Laufzeitfehler: Typ SomeClass existiert nicht (Zeile: 1, Spalte: 12, Index: 11, Token: 'foo').


Mache ich was falsch oder werden Interfaces nicht unterstützt?

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".