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
Formeleditor
dr4g0n76
myCSharp.de - Experte

Avatar #avatar-1768.jpg


Dabei seit:
Beiträge: 2.921
Herkunft: Deutschland

Themenstarter:

Formeleditor

beantworten | zitieren | melden

Oft wünscht man sich einen Formel-Editor. Da ich gerade einen gebraucht habe und dachte, wie stellt man das auf die schnelle an, kam ich auf die Idee reflection zu benutzen.

Zuerst habe ich im Netz nachgesehen und kam auf JScript, dass die Methode Eval benutzt. Diesen Code habe ich dann auch im Projekt belassen.

Aber ich wollte dann eigentlich doch etwas komfortableres haben, das ausbaubarer ist als JScript.

Also habe ich mit C# und dem Compiler eine eigene "Eval"-Funktionalität kreiert. Die übrigens sehr gut funktioniert.

Im Constructor werden die Compiler-Parameter initialisiert und Referenzen auf die benötigten DLLs eingestellt:


        public CReflectiveEvaluator()
        {
            m_CSharpCodeProvider = new CSharpCodeProvider();
            this.m_ICodeCompiler = m_CSharpCodeProvider.CreateCompiler();
            m_CompilerParameters = new CompilerParameters();
            m_CompilerParameters.GenerateInMemory = true;
            m_CompilerParameters.GenerateExecutable = false;
            m_CompilerParameters.ReferencedAssemblies.Add("system.dll");
            m_CompilerParameters.ReferencedAssemblies.Add("mscorlib.dll");
        }

und in eval wird der Code ausgeführt:


        public object Eval(string _sFormula)
        {
            string sSource = this.m_sFormulaTemplateClass.Replace("{1}",_sFormula);
            sSource = sSource.Replace("{0}",CreateVariablesDeclarationsInstructions());
            System.CodeDom.Compiler.CompilerResults cr = m_ICodeCompiler.CompileAssemblyFromSource(this.m_CompilerParameters, sSource);

            Type tMathEval = cr.CompiledAssembly.GetType("CMathEval");
            object oMathEval = Activator.CreateInstance(tMathEval);
            object o = oMathEval.GetType().GetMethod("Eval").Invoke(oMathEval, null);
            
            return o;
        }

Hier kommt noch ein kleiner Trick vor:

Der Konstruktor von der Eval-Klasse sieht so aus:


public object Eval()
{
    {0}
    object o = null;
    o={1};
    return o;
}

Zur Laufzeit werden jetzt die Variablen in {0} geschrieben (mittels String.Replace)
und in {1} wird genau auf die gleiche Weise, die Formel eingefügt.

Wenn jetzt jemand in den Formeleditor z.B. die Variable

a = 5;

und die Formel 4*a eingibt,

dann wird daraus:


public object Eval()
{
    double a = 5;
    object o = null;
    o=4*a;
    return o;
}

Es ist kaum zu glauben, aber das ist alles was benötigt wird, um den Code zu erzeugen und zur Laufzeit auszuführen.

Das Ergebnis wird dann per Invoke ermittelt in die Ergebnis-Textbox eingefügt.
Attachments
Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.
private Nachricht | Beiträge des Benutzers
juetho
myCSharp.de - Member



Dabei seit:
Beiträge: 3.331
Herkunft: Berlin

beantworten | zitieren | melden

Hallo,

bitte korrigiere dringend Titel und Schreibfehler: Es geht ja nicht um Formular, sondern um Formel oder Formula. Danke! Jürgen

PS. Ich wurde sehr verwirrt und habe erst am Ende das eigentliche Thema erkannt.

/Edit: Danke schön!
private Nachricht | Beiträge des Benutzers
dr4g0n76
myCSharp.de - Experte

Avatar #avatar-1768.jpg


Dabei seit:
Beiträge: 2.921
Herkunft: Deutschland

Themenstarter:

beantworten | zitieren | melden

Screenshot:
Attachments
Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.
private Nachricht | Beiträge des Benutzers
Dexter
myCSharp.de - Member



Dabei seit:
Beiträge: 481
Herkunft: Österreich, Vlbg

beantworten | zitieren | melden

Sieht sehr nett aus Was noch eine gute Funktion wäre, und zwar das ganze auch für Graphen realisieren.

Dexter
Programmierer sind Maschinen die Koffein in Quellcode umsetzen.
private Nachricht | Beiträge des Benutzers
dr4g0n76
myCSharp.de - Experte

Avatar #avatar-1768.jpg


Dabei seit:
Beiträge: 2.921
Herkunft: Deutschland

Themenstarter:

beantworten | zitieren | melden

Der Funktionsplotter ist inzwischen auch schon geschrieben, aber noch nicht getestet.
Den werde ich vielleicht nächste Woche auch noch hier posten.

Der Formeleditor hat ein Update erfahren. Es kann jetzt auch gespeichert und geladen werden.

Den Funktionsplotter gibts jetzt auch.
Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.
private Nachricht | Beiträge des Benutzers
Fracoon
myCSharp.de - Member



Dabei seit:
Beiträge: 85

Warnung in VS2008

beantworten | zitieren | melden

Hi dr4g0n76,

erstmal Glückwunsch zu diesem tollen Programm. Funktioniert echt Super.

Ich würde gerne deinen Code in einem meiner Programme benutzen. (Ich hoffe dass geht in Ordnung?!?!?)

Soweit funktioniert alles super außer dass der Kompiler Warnungen (siehe unten) ausgibt. Hängt das an VS2008? Oder Kommen die Warnungen immer? Kann man dass beheben ?

Gruß


Warning	1	'System.CodeDom.Compiler.CodeDomProvider.CreateCompiler()' is obsolete: 'Callers should not use the ICodeCompiler interface and should instead use the methods directly on the CodeDomProvider class. Those inheriting from CodeDomProvider must still implement this interface, and should exclude this warning or also obsolete this method.'	C:\Dokumente und Einstellungen\Seebach\Eigene Dateien\Visual Studio 2008\Projects\Werteeingabe2\werte_control\math\CReflectiveEvaluator.cs	20	36	werte_control
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Fracoon am .
private Nachricht | Beiträge des Benutzers
JunkyXL
myCSharp.de - Experte

Avatar #avatar-3234.gif


Dabei seit:
Beiträge: 1.665
Herkunft: Ein paar Bytes südlich von string

beantworten | zitieren | melden

Scheint so, dass 'System.CodeDom.Compiler.CodeDomProvider.CreateCompiler()' in .NET 3.5 obsolet ist, was es wohl dann in <3.5 nicht war.
private Nachricht | Beiträge des Benutzers
mich4el
myCSharp.de - Member



Dabei seit:
Beiträge: 2

beantworten | zitieren | melden

der Rechner ist super, jedoch hat er durch die Reflection Probleme mit , Zahlen da er . statt , erwartet. Bsp: -> 5/0,5 funktioniert nicht. richtig wäre 5/0.5.

Und ein großes Sicherheitsrisiko durch Reflection ist auch das man schwer prüfen kann, was der User dort eingibt.


BSP: -> Bei der Eingabe System.IO.File.Create("C:\\abc.txt") wird ne datei angelegt.
Damit ist jedem Tür und Tor zum System geöffnet.

Natürlich kann man in dem Frontend so Eingaben filtern und verhindern.
Ansonsten finde ich den Calculator super.
private Nachricht | Beiträge des Benutzers