C# Problem mit .NET Scripting

lordfritte

Lieutenant
Registriert
Juli 2006
Beiträge
993
[GELÖST]Problem mit .NET Scripting

Hallo ich befasse mich zur Zeit mit .NET Scripting und bin schon auf ein Problem gestoßen,
Ich möchte in meinem Programm eine Zeile in meiner Anwendung als Script ausführen.
In meinee Scriptzeile möchte ich ein Objekt(ScriptElements) über eine Variable x nutzen,
hier mein Code:
PHP:
namespace Scripting
{
  public class ScriptingSample
  {
    public void Main(string[] args)
    {
      string sScriptLine = "x.Date();";

      ScriptElements elements = new ScriptElements();
      ScriptManager manager = new ScriptManager();

      Console.WriteLine(manager.RunScript(elements, sScriptLine));

      Console.ReadKey();
    }

  }

  #region ScriptManager

  public class ScriptManager
  {
    ArrayList arrList = new ArrayList();
    public delegate string ScriptRun(ScriptElements x);
    public ScriptRun runDelegate;

    public ScriptManager()
    {
      arrList.Clear();
      arrList.Add("System.dll");
      arrList.Add("System.Windows.Forms.dll");
    }

    public string RunScript(ScriptElements x, string sScriptLine)
    {
      string sRes = "";

      CodeCompileUnit compileUnit = new CodeCompileUnit();
      CodeNamespace nameSpace = new CodeNamespace("Scripting");
      CodeTypeDeclaration reletionClass = new CodeTypeDeclaration("ScriptClass");
      CodeMemberMethod calculationFunction = new CodeMemberMethod();
      CompilerResults compilerResults = null;
      object objFunc;

      compileUnit.Namespaces.Add(nameSpace);
      nameSpace.Imports.Add(new CodeNamespaceImport("System"));
      nameSpace.Imports.Add(new CodeNamespaceImport("MyConsoleSample"));
      nameSpace.Imports.Add(new CodeNamespaceImport("MyConsoleSample.codes"));
      nameSpace.Types.Add(reletionClass);
      reletionClass.IsClass = true;
      reletionClass.TypeAttributes = System.Reflection.TypeAttributes.Public;
      reletionClass.Members.Add(calculationFunction);
      calculationFunction.Attributes = MemberAttributes.Public;
      calculationFunction.ReturnType = new CodeTypeReference(typeof(string));
      calculationFunction.Name = "Run";
      calculationFunction.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ScriptElements), "x"));
      calculationFunction.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression(sScriptLine)));

      CompilerParameters compilerParameters = new CompilerParameters();
      compilerParameters.GenerateInMemory = true;

      CSharpCodeProvider csharp = new CSharpCodeProvider();
      compilerResults = csharp.CompileAssemblyFromDom(compilerParameters, compileUnit);

      if ((compilerResults != null) && (compilerResults.Errors.Count > 0))
      {
        for (int i = 0; i < compilerResults.Errors.Count; i++)
        {
          MessageBox.Show(compilerResults.Errors[i].ToString());
        }
      }
      else
      {
        objFunc = compilerResults.CompiledAssembly.CreateInstance("Scripting.ScriptClass", true);
        runDelegate = (ScriptRun)Delegate.CreateDelegate(typeof(ScriptRun), objFunc, calculationFunction.Name);

        if (runDelegate != null)
          sRes = runDelegate(x);
      }

      return sRes;
    }
  }

  #endregion

  #region ScriptElements

  public class ScriptElements
  {
    public ScriptElements()
    { }

    public string Date()
    {
      return DateTime.Now.ToString();
    }
  }

  #endregion
}

Mein Problem ist nun ganz einfach, wenn ich das laufen lasse bekomme ich über die MessageBox folgenden Fehler:
Der Typ- oder namespacename ScriptElements ist im Namespace Scripting nicht vorhanden. (Fehlt eine Assemblyverweis?).
Wie bekomme ich das ganze zum laufen?
Wenn ich ScriptElements durch z.b. float ersetze, zum rechnen, läuft es wunderbar.
 
Zuletzt bearbeitet: (Problem gelöst)
mh,

add reference

System.Windows.Forms

dann ist der fehler weg.

Danach wird es trotzdem nicht laufen, da kein einsprungpunkt gefunden wird, es gibt kein public bei ohne static (Der einsprungpunkt muss statisch sein, und dann ist public obsolete) ;) (btw ohne modifier ist die methode internal)

Ersetze public durch static.

evtl. klappts dann besser ;)

EDIT: Installier dir das englische VS, damit kannste dann auch Fehler googlen. Google wird dein bester helfer beim entwickeln ;)
 
Zuletzt bearbeitet:
kreadon schrieb:
mh,

add reference

System.Windows.Forms

dann ist der fehler weg.

Danach wird es trotzdem nicht laufen, da kein einsprungpunkt gefunden wird, es gibt kein public bei ohne static (Der einsprungpunkt muss statisch sein, und dann ist public obsolete) ;) (btw ohne modifier ist die methode internal)

Ersetze public durch static.

evtl. klappts dann besser ;)

EDIT: Installier dir das englische VS, damit kannste dann auch Fehler googlen. Google wird dein bester helfer beim entwickeln ;)


1. Habe ich die System.Windows.Forms doch hinzuigefügt: arrList.Add("System.Windows.Forms.dll"); oO
2. Habe ich geschrieben, wenn ich ScriptElements, eine Klasse von mir, durch float, int, long, etc. ersetze, läuft es.
3. Wenn du mir das englische VS bezahlst
 
zu1:schoen das es klappt.

zu2: ich habe deine klasse nicht, daher kann ich es nicht nachstellen :)

zu 3: Nun offensichtlich hast du dir das deu VS leisten koennen. (falls du student bist, frage mal bei denen nach. oder verwende die kostenlose express edition). Und wenn nicht mach deinen cheffes klar das das englische VS zeit spart.

Beim naechsten upgrade auf die engl. Version achten.
 
zu 2: Die steht doch da in meinem Codebeispiel, ganz unten:
PHP:
public class ScriptElements
  {
    public ScriptElements()
    { }

    public string Date()
    {
      return DateTime.Now.ToString();
    }
  }

Ja ist bis her ganz klein, aber ist ja auch nur zum Testen.
Ich verstehe sie nicht warum er sie nicht finden, die Klasse ist im selben Namespace, sie ist in der selbe assembly, also ich habe kein Ahnung.

EDIT:

Ok, Problem ist schon gelöst, es fehlte das:
PHP:
List<string> assemblyNames = new List<string>();
      foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
      {
        if((asm.Location != null) && (asm.Location.Length > 0))
          assemblyNames.Add(new Uri(asm.Location).LocalPath);
      }
      compileUnit.ReferencedAssemblies.AddRange(assemblyNames.ToArray());
 
Zuletzt bearbeitet:
Zurück
Oben