Vra

Ek kan nie'n eval("something()"); uit te voer die kode dinamies in JavaScript.Is daar'n manier vir my om dieselfde ding te doen in C#?

'n voorbeeld van wat ek probeer om te doen, is:Ek het'n heelgetal veranderlike (sê i) en ek het verskeie eienskappe deur die name:"Property1", "Property2", "Property3", ens.Nou, ek wil om uit te voer'n paar bedrywighede op die " Eiendomek "eiendom afhangende van die waarde van i.

Dit is regtig eenvoudig met Javascript.Is daar enige manier om dit te doen met C#?

Was dit nuttig?

Oplossing

Ongelukkig C # is nie 'n dinamiese taal soos dit.

Wat jy kan doen, is egter 'n C # bron-kode lêer, vol met klas en alles skep, en voer dit deur die CodeDom verskaffer vir C # en stel dit in 'n vergadering, en dan uit te voer nie.

Hierdie forum post op MSDN bevat 'n antwoord met 'n paar voorbeeld kode in die bladsy ietwat:
skep 'n anonieme metode van 'n string?

Ek sou skaars sê dit is 'n baie goeie oplossing, maar dit is moontlik in elk geval.

Watter soort kode gaan jy verwag in die tou? As dit is 'n klein subset van geldige kode, byvoorbeeld net wiskunde uitdrukkings, kan dit wees dat ander alternatiewe bestaan.


Edit : Wel, wat my leer om die vrae deeglik eerste lees. Ja, besinning sou in staat wees om jou hier gee 'n paar help.

As jy die string verdeel deur die; eerste, individuele eiendomme te kry, kan jy die volgende kode te gebruik om 'n PropertyInfo voorwerp te kry vir 'n bepaalde eiendom vir 'n klas, en dan gebruik wat beswaar teen 'n spesifieke voorwerp te manipuleer.

String propName = "Text";
PropertyInfo pi = someObject.GetType().GetProperty(propName);
pi.SetValue(someObject, "New Value", new Object[0]);

Link: PropertyInfo.SetValue metode

Ander wenke

Die gebruik van die Roslyn script API (meer monsters hier ):

// add NuGet package 'Microsoft.CodeAnalysis.Scripting'
using Microsoft.CodeAnalysis.CSharp.Scripting;

await CSharpScript.EvaluateAsync("System.Math.Pow(2, 4)") // returns 16

Jy kan ook enige stuk kode hardloop:

var script = await CSharpScript.RunAsync(@"
                class MyClass
                { 
                    public void Print() => System.Console.WriteLine(1);
                }")

En verwys na die kode wat gegenereer is in die vorige lopies:

await script.ContinueWithAsync("new MyClass().Print();");

Nie regtig nie. Jy kan weerspieëling gebruik om te bereik wat jy wil, maar dit sal nie naastenby so eenvoudig soos in Javascript wees. Byvoorbeeld, as jy wou die private terrein van 'n voorwerp om iets te stel, kan jy hierdie funksie te gebruik:

protected static void SetField(object o, string fieldName, object value)
{
   FieldInfo field = o.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
   field.SetValue(o, value);
}

Dit is 'n eval funksie onder c #. Ek gebruik dit om anoniem funksies (Lambda Expressions) omskep uit 'n string. Bron: http://www.codeproject.com/KB/cs/evalcscode.aspx

public static object Eval(string sCSCode) {

  CSharpCodeProvider c = new CSharpCodeProvider();
  ICodeCompiler icc = c.CreateCompiler();
  CompilerParameters cp = new CompilerParameters();

  cp.ReferencedAssemblies.Add("system.dll");
  cp.ReferencedAssemblies.Add("system.xml.dll");
  cp.ReferencedAssemblies.Add("system.data.dll");
  cp.ReferencedAssemblies.Add("system.windows.forms.dll");
  cp.ReferencedAssemblies.Add("system.drawing.dll");

  cp.CompilerOptions = "/t:library";
  cp.GenerateInMemory = true;

  StringBuilder sb = new StringBuilder("");
  sb.Append("using System;\n" );
  sb.Append("using System.Xml;\n");
  sb.Append("using System.Data;\n");
  sb.Append("using System.Data.SqlClient;\n");
  sb.Append("using System.Windows.Forms;\n");
  sb.Append("using System.Drawing;\n");

  sb.Append("namespace CSCodeEvaler{ \n");
  sb.Append("public class CSCodeEvaler{ \n");
  sb.Append("public object EvalCode(){\n");
  sb.Append("return "+sCSCode+"; \n");
  sb.Append("} \n");
  sb.Append("} \n");
  sb.Append("}\n");

  CompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString());
  if( cr.Errors.Count > 0 ){
      MessageBox.Show("ERROR: " + cr.Errors[0].ErrorText, 
         "Error evaluating cs code", MessageBoxButtons.OK, 
         MessageBoxIcon.Error );
      return null;
  }

  System.Reflection.Assembly a = cr.CompiledAssembly;
  object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler");

  Type t = o.GetType();
  MethodInfo mi = t.GetMethod("EvalCode");

  object s = mi.Invoke(o, null);
  return s;

}

Ek het 'n open source projek geskryf, Dynamic Expresso , wat teks uitdrukking kan omskep geskryf met behulp van 'n C # sintaksis in afgevaardigdes (of uitdrukking boom). Uitdrukkings word ontleed en omskep in Expression Bome sonder die gebruik van samestelling of besinning.

Jy kan iets soos skryf:

var interpreter = new Interpreter();
var result = interpreter.Eval("8 / 2 + 2");

of

var interpreter = new Interpreter()
                      .SetVariable("service", new ServiceExample());

string expression = "x > 4 ? service.SomeMethod() : service.AnotherMethod()";

Lambda parsedExpression = interpreter.Parse(expression, 
                          new Parameter("x", typeof(int)));

parsedExpression.Invoke(5);

My werk is gebaseer op Scott Gu artikel http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic- navraag-library.aspx .

Al wat sal beslis werk. Persoonlik, vir daardie spesifieke probleem, ek sou waarskynlik 'n bietjie ander benadering te neem. Miskien iets soos hierdie:

class MyClass {
  public Point point1, point2, point3;

  private Point[] points;

  public MyClass() {
    //...
    this.points = new Point[] {point1, point2, point3};
  }

  public void DoSomethingWith(int i) {
    Point target = this.points[i+1];
    // do stuff to target
  }
}

By die gebruik van patrone soos hierdie, jy moet versigtig wees dat jou data gestoor word deur verwysing en nie deur waarde te wees. Met ander woorde, dit nie doen nie met primitiewes. Jy moet hulle groot opgeblase klas eweknieë gebruik.

Ek het besef dit is nie presies die vraag, maar die vraag is redelik goed beantwoord en ek het gedink miskien 'n alternatiewe benadering kan help.

Ek doen nie nou as jy absoluut wil C # state uit te voer, maar jy kan reeds Javascript state in C 2.0 # voer. Die open-source biblioteek JINT in staat is om dit te doen. Dit is 'n Javascript tolk vir NET. Slaag 'n Javascript program en dit sal loop in jou aansoek. Jy kan selfs slaag C # voorwerp as argumente en doen outomatisering op dit.

Ook as jy net wil uitdrukking op jou eiendom te evalueer, te probeer om NCalc .

Jy kan gebruik refleksie om die eiendom te kry en roep dit.Iets soos hierdie:

object result = theObject.GetType().GetProperty("Property" + i).GetValue(theObject, null);

Dit is, met die veronderstelling dat die voorwerp wat die eiendom is die sogenaamde "theObject" :)

Jy kan ook 'n webblaaier te implementeer, dan laai 'n HTML-lêer wat ring bevat JavaScript.

Toe gaan u vir die document.InvokeScript Metode op hierdie leser. Die terugkeer waarde van die eval funksie kan gevang en omskep in alles wat jy nodig het.

Ek het dit in verskeie projekte en dit werk perfek.

Hoop dit help

Jy kan dit doen met 'n prototipe funksie:

void something(int i, string P1) {
    something(i, P1, String.Empty);
}

void something(int i, string P1, string P2) {
    something(i, P1, P2, String.Empty);
}

void something(int i, string P1, string P2, string P3) {
    something(i, P1, P2, P3, String.Empty);
}

en so aan ...

Gebruik besinning te ontleed en 'n data bindend uitdrukking teen 'n voorwerp te evalueer te hardloop tyd.

DataBinder.Eval Metode

Ek het 'n pakket geskryf, SharpByte.Dynamic , om die taak van die opstel en uitvoering van kode dinamies te vereenvoudig. Die kode kan opgeroep op enige konteks voorwerp met behulp van uitbreiding metodes soos uiteengesit verdere hier .

Byvoorbeeld,

someObject.Evaluate<int>("6 / {{{0}}}", 3))

terug 3;

someObject.Evaluate("this.ToString()"))

terug string verteenwoordiging uit die samehang voorwerp se;

someObject.Execute(@
"Console.WriteLine(""Hello, world!"");
Console.WriteLine(""This demonstrates running a simple script"");
");

loop daardie state as 'n script, ens

Executables kan maklik gekry met behulp van 'n fabriek metode, soos gesien in die voorbeeld hier --all wat jy nodig het is die bron-kode en lys van enige verwagte vernoem parameters (tekens is ingesluit die gebruik van drie-hakienotasie, soos {{{0}}}, om botsings met string.Format () sowel as handvatsels-agtige syntaxes) te vermy:

IExecutable executable = ExecutableFactory.Default.GetExecutable(executableType, sourceCode, parameterNames, addedNamespaces);

Elke uitvoerbare voorwerp (script of uitdrukking) is draad-veilige, kan gestoor word en weer gebruik, ondersteun meld vanuit 'n script, winkels tydsberekening inligting en laaste uitsondering as teëgekom, ens Daar is ook 'n afskrif () metode saamgestel op elke toe te laat skep goedkoop eksemplare, dit wil sê die gebruik van 'n uitvoerbare voorwerp saamgestel uit 'n script of uitdrukking as 'n sjabloon vir die skep van ander.

Oorhoofse van die uitvoering van 'n reeds-saamgestel script of stelling is relatief laag, by goed onder 'n micro op beskeie hardeware, en al-saamgestel skrifte en uitdrukkings word kas vir hergebruik.

Ek het probeer om 'n waarde van 'n struktuur (klas) lid kry deur dit se naam. Die struktuur is nie dinamies. Alle antwoorde het nie gewerk nie, totdat ek het dit uiteindelik:

public static object GetPropertyValue(object instance, string memberName)
{
    return instance.GetType().GetField(memberName).GetValue(instance);
}

Hierdie metode sal die waarde van die lid terug te keer deur dit se naam. Dit werk op gereelde struktuur (klas).

Jy kan die Heleonix.Reflection biblioteek kontroleer. Dit bied metodes om dinamies te kry / stel / te roep lede, insluitend sub-lede, of as 'n lid duidelik gedefinieer, kan jy 'n lucky / setter (lambda saamgestel in 'n afgevaardigde) wat vinniger te skep as weerspieëling:

var success = Reflector.Set(instance, null, $"Property{i}", value);

Of as aantal eiendomme is nie eindeloos, kan jy etters genereer en chache hulle (etters is vinniger omdat hulle saamgestel afgevaardigdes):

var setter = Reflector.CreateSetter<object, object>($"Property{i}", typeof(type which contains "Property"+i));
setter(instance, value);

Setters kan van tipe Action<object, object> wees, maar gevalle kan verskillende tydens looptyd wees, sodat jy kan lyste van etters skep.

Ongelukkig C # hoef nie 'n naturel fasiliteite om dit te doen presies wat jy vra.

Maar my C # eval program toelaat vir die evaluering van C # kode. Dit maak voorsiening vir die evaluering van C # kode tydens looptyd en ondersteun baie C # state. Trouens, hierdie kode is bruikbare binne enige NET projek, maar dit is beperk tot die gebruik van C # sintaksis. Het jy 'n blik op my webwerf, http://csharp-eval.com , vir meer besonderhede.

Die korrekte antwoord is wat jy nodig het om al die gevolg kas na die mem0ry gebruik laag te hou.

'n voorbeeld sou lyk hierdie

TypeOf(Evaluate)
{
"1+1":2;
"1+2":3;
"1+3":5;
....
"2-5":-3;
"0+0":1
} 

en voeg dit by 'n Lys

List<string> results = new List<string>();
for() results.Add(result);

red die id en gebruik dit in die kode

Hoop dit help

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top