[C#] Problem beim kompilieren eines Lambda Ausdrucks zur Laufzeit

Turri

Erfahrenes Mitglied
Hallo,

bei mir funktioniert dein Code.
Zeig mal etwas mehr Code, vielleicht liegts in der Zeile davor oder sowas.
 

GalaxyWarrior

Erfahrenes Mitglied
Der Code an sich geht schon.
Erst wenn ich ihn mit einem Programm zur Laufzeit kompilieren will geht es nicht.

Zuerst , wie im Tutorial beschrieben, packe ich meinen Code in einen StringBuilder

Code:
sb.Append("        public void Ping(object o)\r\n");
            sb.Append("        {\r\n");
            sb.Append("            IPAddress<string> ip = (IPAddress<string>)o;\r\n");
            sb.Append("            string stat = \"\";\r\n");
            sb.Append("            try\r\n");
            sb.Append("            {\r\n");
            sb.Append("                List<long> stats = new List<long>();\r\n");
            sb.Append("                do\r\n");
            sb.Append("                {\r\n");
            sb.Append("                    long lat = ip.Latency(retry, timeout);\r\n");
            sb.Append("                    stats.Add(lat);\r\n");
            sb.Append("                    string message = null;\r\n");
            sb.Append("                    long mid = 0;\r\n");
            sb.Append("                    foreach (long l in stats.Where(v => v != long.MinValue))\r\n");
            sb.Append("                        mid += l;\r\n");
            sb.Append("\r\n");
            sb.Append("                    if (stats.Count(v => v != long.MinValue) > 0)\r\n");
            sb.Append("                    {\r\n");
            sb.Append("                        mid = (mid / stats.Count(v => v != long.MinValue));\r\n");
            sb.Append("                    }\r\n");
            sb.Append("                    else\r\n");
            sb.Append("                    {\r\n");
            sb.Append("                        mid = 0;\r\n");
            sb.Append("                    }\r\n");
            sb.Append("\r\n");
            sb.Append("                    long latenzMin = long.MinValue;\r\n");
            sb.Append("                    try\r\n");
            sb.Append("                    {\r\n");
            sb.Append("                        latenzMin = stats.Where(v => v != long.MinValue).Min();\r\n");
            sb.Append("                    }\r\n");
            sb.Append("                    catch { }\r\n");
            sb.Append("\r\n");
            sb.Append("                    long latenzMax = long.MinValue;\r\n");
            sb.Append("                    try\r\n");
            sb.Append("                    {\r\n");
            sb.Append("                        latenzMax = stats.Where(v => v != long.MinValue).Max();\r\n");
            sb.Append("                    }\r\n");
            sb.Append("                    catch { }\r\n");
            sb.Append("\r\n");
            sb.Append("                    stat = \"Pingstatistik für \" + ip + \":\" + Environment.NewLine +\r\n");
            sb.Append("                        \"\tPakete: Gesendet = \" + stats.Count + \", Empfangen = \" + stats.Count(v => v != long.MinValue) +\r\n");
            sb.Append("                        \", Verloren = \" + stats.Count(v => v == long.MinValue) +\r\n");
            sb.Append("                        Environment.NewLine;\r\n");
            sb.Append("                    if (latenzMax != long.MinValue && latenzMin != long.MinValue)\r\n");
            sb.Append("                        stat += \"Latenz:\" + Environment.NewLine + \"\tMinimum = \" + latenzMin + \"ms, Maximum = \" + latenzMax +\r\n");
            sb.Append("                            \"ms, Mittelwert = \" + mid + \"ms\";\r\n");
            sb.Append("\r\n");
            sb.Append("                    if (lat == long.MinValue)\r\n");
            sb.Append("                        message = DateTime.UtcNow.ToString() + \" :> \" + ip.ToString() + \": \" + \"timeout\" + Environment.NewLine;\r\n");
            sb.Append("                    else\r\n");
            sb.Append("                        message = DateTime.UtcNow.ToString() + \" :> \" + ip.ToString() + \": \" + lat + \"ms\" + Environment.NewLine;\r\n");
            sb.Append("\r\n");
            sb.Append("                    using (TextWriter tw2 = new StreamWriter(logDir + \"/\" + ip + \".log\", true))\r\n");
            sb.Append("                    {\r\n");
            sb.Append("                        tw2.Write(message);\r\n");
            sb.Append("                    }\r\n");
            sb.Append("                    WriteTextNew(message + \"|\" + stat + \"|\" + ip.ToString());\r\n");
            sb.Append("                    Thread.Sleep(interval);\r\n");
            sb.Append("                } while (!stop);\r\n");
            sb.Append("            }\r\n");
            sb.Append("            catch (Exception e)\r\n");
            sb.Append("            {\r\n");
            sb.Append("                if (verbose)\r\n");
            sb.Append("                    ShowMessageBox(e.Message + Environment.NewLine + e.StackTrace + Environment.NewLine + Environment.NewLine +\r\n");
            sb.Append("                        e.InnerException, \"Exception thrown\", MessageBoxButtons.OK);\r\n");
            sb.Append("            }\r\n");
            sb.Append("            finally\r\n");
            sb.Append("            {\r\n");
            sb.Append("                try\r\n");
            sb.Append("                {\r\n");
            sb.Append("                    using (TextWriter tw2 = new StreamWriter(logDir + \"/\" + ip + \".log\", true))\r\n");
            sb.Append("                    {\r\n");
            sb.Append("                        tw2.Write(Environment.NewLine + stat);\r\n");
            sb.Append("                    }\r\n");
            sb.Append("                    if (restart) File.Delete(logDir + \"/\" + ip + \".log\");\r\n");
            sb.Append("                }\r\n");
            sb.Append("                catch (Exception e)\r\n");
            sb.Append("                {\r\n");
            sb.Append("                    if (verbose)\r\n");
            sb.Append("                        WriteText(e.Message);\r\n");
            sb.Append("                }\r\n");
            sb.Append("            }\r\n");
            sb.Append("        }\r\n");

Das ist die komplette Methode. Der gesammte Code würde den Rahmen hier etwas sprengen.

Dann wird das ganze am Ende mit

Code:
            Sourcecode = sb.ToString();
            CompilerResults ret = compiler.CompileAssemblyFromSource(compArgs, Sourcecode);

kompiliert.

Ansich sollte das laufen, da ich den Code den ich dynamisch erzeuge so wie er momentan existiert auch schon als eigenes Programm laufen habe, bis auf ein paar kleine Änderungen die man über Textfeld eingeben kann, aber nicht diese Methode betreffen.

Gruß GalaxyWarrior
 

Turri

Erfahrenes Mitglied
Ich habs bei mir ausprobiert und bekomme den selben Fehler.
Wobei es aber eine Reihe von Fehlern ist, die durch die foreach ausgelöst werden.

Dummerweise steht im Tutorial das hier:

C#:
if (ret.Errors.Count > 0)
{
  errString = ret.Errors[0].ToString(); // liefert den ersten Fehler zurück
  return false; // ERROR
}

Dann sieht man aber nur den ersten.
Aber scheinbar kommt der "OnTheFly" Compiler mit so einem Ausdruck wirklich nicht klar.

Bin auch auf eine Lösung gespannt ^^
 

GalaxyWarrior

Erfahrenes Mitglied
Ja dass da mehrere Fehler entstehen ist mir klar, allerdings bemängeln die ja alle die Lambda Ausdrücke. Wenn ich alle '=>' durch '==' ersetze sind die Fehler weg.

Ich meine ich werde das auch irgendwie ohne Lambda Ausdrücke hinbekommen, aber dann wirds etwas fuddelig ;)

Falls einer eine Lösung hat, immer her damit

[EDIT]
Ich glaube das Problem ist, dass ein falsches Framework verwendet wird.
Ich habe jetzt die Lambda Ausdrücke eliminiert und bekomme nun den Fehler dass List<long> keine definition für Min() enthält. Das Spricht für mich dafür, dass der On the Fly Compiler .Net < 3.5 verwendet.

Mal schaun ob man das irgendwo definieren kann.
[/EDIT]

Gruß GalaxyWarrior
 
Zuletzt bearbeitet:

Turri

Erfahrenes Mitglied
Hallo,

habs hinbekommen.
Man muss wirklich die Compilerversion umstellen.
.NET 2.0 ist Default auch wenn man ein 3.5 Projekt angelegt hat ^^.

C#:
var providerOptions = new Dictionary<string, string>();
providerOptions.Add("CompilerVersion", "v3.5");
CodeDomProvider compiler = new CSharpCodeProvider(providerOptions);
CompilerParameters compArgs = new CompilerParameters();
....

Habs hier gefunden.

Link