मैं गतिशील रूप से सी # कोड का मूल्यांकन कैसे कर सकता हूं?

मैं एक eval ("कुछ ()") कर सकता हूं; जावास्क्रिप्ट में गतिशील रूप से कोड निष्पादित करने के लिए। क्या सी # में वही काम करने का कोई तरीका है?

मैं जो करने का प्रयास कर रहा हूं उसका एक उदाहरण यह है: मेरे पास एक पूर्णांक चर है (कहें i ) और मेरे नामों से कई गुण हैं: "प्रॉपर्टी 1", "प्रॉपर्टी 2", "प्रॉपर्टी 3" इत्यादि। अब, मैं i के मान के आधार पर "संपत्ति i " संपत्ति पर कुछ संचालन करना चाहता हूं।

यह जावास्क्रिप्ट के साथ वास्तव में सरल है। क्या सी # के साथ ऐसा करने का कोई तरीका है?

0
ro fr bn
@ पीटर लांग, मैं आयरनपीथन के eval पर दस्तावेज कहां मिल सकता है?
जोड़ा लेखक smartcaveman, स्रोत
सी # कॉल ironpython eval। मैंने इसे सी # 4.0 में करने की कोशिश की। सी # 2.0 के साथ कोई अनुभव नहीं है
जोड़ा लेखक Peter Long, स्रोत
मोनो सीएसएचआरपी इंटरैक्टिव शैल पर एक नज़र डालें। इसमें eval-like functions है।
जोड़ा लेखक Igor Brejc, स्रोत

15 उत्तर

यह सब निश्चित रूप से काम करेगा। व्यक्तिगत रूप से, उस विशेष समस्या के लिए, मैं शायद थोड़ा अलग दृष्टिकोण लेगा। शायद इस तरह कुछ:

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
  }
}

इस तरह के पैटर्न का उपयोग करते समय, आपको सावधान रहना होगा कि आपका डेटा संदर्भ द्वारा संग्रहीत किया जाता है, न कि मूल्य से। दूसरे शब्दों में, primitives के साथ ऐसा मत करो। आपको अपने बड़े ब्लोएटेड क्लास समकक्षों का उपयोग करना होगा।

मुझे एहसास हुआ कि वास्तव में सवाल नहीं है, लेकिन सवाल का बहुत अच्छा जवाब दिया गया है और मैंने सोचा कि शायद एक वैकल्पिक दृष्टिकोण मदद कर सकता है।

0
जोड़ा

आप प्रोटोटाइप फ़ंक्शन के साथ ऐसा कर सकते हैं:

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);
}

और इसी तरह...

0
जोड़ा

ज़रुरी नहीं। आप जो चाहते हैं उसे प्राप्त करने के लिए प्रतिबिंब का उपयोग कर सकते हैं, लेकिन यह जावास्क्रिप्ट में लगभग उतना आसान नहीं होगा। उदाहरण के लिए, यदि आप किसी ऑब्जेक्ट का निजी फ़ील्ड किसी चीज़ पर सेट करना चाहते हैं, तो आप इस फ़ंक्शन का उपयोग कर सकते हैं:

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

दुर्भाग्यवश, सी # उस तरह की गतिशील भाषा नहीं है।

हालांकि, आप क्या कर सकते हैं, सी # स्रोत कोड फ़ाइल बनाना, कक्षा और सबकुछ से भरा हुआ है, और इसे कोडडॉम प्रदाता के माध्यम से सी # के लिए चलाएं और इसे एक असेंबली में संकलित करें, और फिर इसे निष्पादित करें।

This forum post on MSDN contains an answer with some example code down the page somewhat:
create a anonymous method from a string?

मैं शायद ही कहूंगा कि यह एक बहुत अच्छा समाधान है, लेकिन वैसे भी यह संभव है।

उस स्ट्रिंग में आप किस प्रकार के कोड की उम्मीद कर रहे हैं? यदि यह मान्य कोड का मामूली सबसेट है, उदाहरण के लिए केवल गणित अभिव्यक्तियां, तो हो सकता है कि अन्य विकल्प मौजूद हों।


Edit: Well, that teaches me to read the questions thoroughly first. Yes, reflection would be able to give you some help here.

यदि आप स्ट्रिंग को विभाजित करते हैं; सबसे पहले, व्यक्तिगत गुण प्राप्त करने के लिए, आप किसी वर्ग के लिए किसी विशेष संपत्ति के लिए PropertyInfo ऑब्जेक्ट प्राप्त करने के लिए निम्न कोड का उपयोग कर सकते हैं, और उसके बाद उस ऑब्जेक्ट का उपयोग किसी विशेष ऑब्जेक्ट में हेरफेर करने के लिए कर सकते हैं।

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

Link: PropertyInfo.SetValue Method

0
जोड़ा

मैंने एक ओपन सोर्स प्रोजेक्ट लिखा है, डायनामिक एक्सप्रेसो , जो एक सी # सिंटैक्स का उपयोग करके लिखी गई पाठ अभिव्यक्ति को परिवर्तित कर सकता है प्रतिनिधियों (या अभिव्यक्ति पेड़)। अभिव्यक्तियों को संकलित या प्रतिबिंबित किए बिना अभिव्यक्ति पेड़ में पार्स किया गया है और परिवर्तित किया गया है।

आप कुछ लिख सकते हैं जैसे:

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

या

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 wयाk is based on Scott Gu article http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx .

0
जोड़ा

रन टाइम पर किसी ऑब्जेक्ट के विरुद्ध डेटा-बाध्यकारी अभिव्यक्ति को पार्स और मूल्यांकन करने के प्रतिबिंब का उपयोग करता है।

DataBinder.Eval विधि

0
जोड़ा
क्या आप एक उदाहरण दिखा सकते हैं?
जोड़ा लेखक Nick Binnet, स्रोत

अब मैं नहीं हूं कि आप पूरी तरह से सी # कथन निष्पादित करना चाहते हैं, लेकिन आप पहले ही सी # 2.0 में जावास्क्रिप्ट स्टेटमेंट निष्पादित कर सकते हैं। ओपन-सोर्स लाइब्रेरी जिंट इसे करने में सक्षम है। यह .NET के लिए जावास्क्रिप्ट दुभाषिया है। एक जावास्क्रिप्ट प्रोग्राम पास करें और यह आपके आवेदन के अंदर चला जाएगा। आप सी # ऑब्जेक्ट को तर्क के रूप में भी पास कर सकते हैं और उस पर स्वचालन कर सकते हैं।

अगर आप अपनी संपत्तियों पर अभिव्यक्ति का मूल्यांकन करना चाहते हैं, तो NCalc को आज़माएं।

0
जोड़ा

Roslyn स्क्रिप्टिंग API का उपयोग करना (अधिक यहां नमूने ):

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

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

आप कोड का कोई भी टुकड़ा चला सकते हैं:

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

और पिछले रनों में उत्पन्न कोड को संदर्भित करें:

await script.ContinueWithAsync("new MyClass().Print();");
0
जोड़ा

दुर्भाग्यवश, सी # में जो कुछ भी आप पूछ रहे हैं, उसके लिए कोई मूल सुविधाएं नहीं हैं।

हालांकि, मेरा सी # eval प्रोग्राम सी # कोड का मूल्यांकन करने की अनुमति देता है। यह रनटाइम पर सी # कोड का मूल्यांकन करने के लिए प्रदान करता है और कई सी # कथन का समर्थन करता है। वास्तव में, यह कोड किसी भी .NET प्रोजेक्ट के भीतर प्रयोग योग्य है, हालांकि, यह सी # सिंटैक्स का उपयोग करने तक ही सीमित है। अतिरिक्त जानकारी के लिए, मेरी वेबसाइट पर एक नज़र डालें, http://csharp-eval.com

0
जोड़ा
Roslyn Scripting API पर एक नज़र डालें
जोड़ा लेखक Andrey-WD, स्रोत

आप संपत्ति प्राप्त करने और इसे आमंत्रित करने के लिए प्रतिबिंब का उपयोग कर सकते हैं। कुछ इस तरह:

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

यही है, उस वस्तु को मानते हुए जिसमें संपत्ति है उसे "theObject" कहा जाता है :)

0
जोड़ा

आप वेबब्रोसर को भी कार्यान्वित कर सकते हैं, फिर एक HTML-फ़ाइल लोड करें जिसमें जावास्क्रिप्ट शामिल है।

फिर आप इस ब्राउज़र पर document.InvokeScript विधि के लिए जाते हैं। Eval फ़ंक्शन का रिटर्न वैल्यू कैच किया जा सकता है और आपको जो भी चाहिए उसे बदल दिया जा सकता है।

मैंने इसे कई परियोजनाओं में किया और यह पूरी तरह से काम करता है।

आशा करता हूँ की ये काम करेगा

0
जोड़ा

This is an eval function under c#. I used it to convert anonymous functions (Lambda Expressions) from a string. Source: 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;

}
0
जोड़ा
@sehe Whoops, मैंने टाइपो (Lambada => Lambda) को सही किया। मुझे नहीं पता था कि गीत को लम्बाडा कहा जाता है, इसलिए यह एक अनजान था। ;)
जोड़ा लेखक Largo, स्रोत

सही जवाब है कि आपको mem0ry उपयोग को कम रखने के लिए सभी परिणामों को कैश करने की आवश्यकता है।

एक उदाहरण इस तरह दिखेगा

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

और इसे एक सूची में जोड़ें

List results = new List();
for() results.Add(result);

आईडी को सहेजें और कोड में इसका इस्तेमाल करें

उम्मीद है की यह मदद करेगा

0
जोड़ा
किसी ने लुकअप के साथ मूल्यांकन भ्रमित किया। यदि आप सभी संभावित कार्यक्रमों को जानते हैं (I सोचें जो कम से कम एनपी-हार्ड है) ... और आपके पास सभी संभावित परिणामों को प्रीकंपाइल करने के लिए सुपरमाचिन है ... और कोई दुष्प्रभाव / बाहरी इनपुट नहीं हैं ... हाँ, यह विचार सैद्धांतिक रूप से काम करता है। हालांकि कोड एक बड़ी वाक्यविन्यास त्रुटि है
जोड़ा लेखक sehe, स्रोत
उहम्म ... तुम्हारा क्या मतलब है?
जोड़ा लेखक xfix, स्रोत

मैंने एक पैकेज लिखा है, SharpByte गतिशील , कोड को गतिशील रूप से संकलित और निष्पादित करने के कार्य को सरल बनाने के लिए। विस्तार विधियों का उपयोग करके किसी भी संदर्भ ऑब्जेक्ट पर कोड को आगे बढ़ाया जा सकता है जैसा कि विस्तृत किया गया है यहां

उदाहरण के लिए,

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

रिटर्न 3;

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

संदर्भ ऑब्जेक्ट की स्ट्रिंग प्रस्तुति देता है;

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

उन बयानों को एक स्क्रिप्ट, आदि के रूप में चलाता है

Executables can be gotten easily using a factory method, as seen in the example here--all you need is the source code and list of any expected named parameters (tokens are embedded using triple-bracket notation, such as {{{0}}}, to avoid collisions with string.Format() as well as Handlebars-like syntaxes):

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

प्रत्येक निष्पादन योग्य ऑब्जेक्ट (स्क्रिप्ट या अभिव्यक्ति) थ्रेड-सुरक्षित है, संग्रहीत और पुन: उपयोग किया जा सकता है, किसी स्क्रिप्ट के भीतर से लॉगिंग का समर्थन करता है, समय की जानकारी संग्रहीत करता है और यदि सामना किया जाता है तो अंतिम अपवाद आदि। प्रत्येक पर संकलित एक प्रतिलिपि() विधि भी है सस्ते प्रतियां बनाना, यानी दूसरों को बनाने के लिए टेम्पलेट के रूप में एक स्क्रिप्ट या अभिव्यक्ति से संकलित निष्पादन योग्य ऑब्जेक्ट का उपयोग करना।

पहले से संकलित स्क्रिप्ट या कथन निष्पादित करने का ओवरहेड अपेक्षाकृत कम है, साथ ही मामूली हार्डवेयर पर एक माइक्रोसेकंड के तहत, और पहले से संकलित स्क्रिप्ट और अभिव्यक्तियों को पुन: उपयोग के लिए कैश किया जाता है।

0
जोड़ा

मैं इसके नाम से एक संरचना (वर्ग) सदस्य का मूल्य प्राप्त करने की कोशिश कर रहा था। संरचना गतिशील नहीं थी। जब तक मुझे अंत में यह नहीं मिला तब तक सभी उत्तरों काम नहीं करते थे:

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

यह विधि सदस्य के मूल्य को इसके नाम से वापस कर देगी। यह नियमित संरचना (कक्षा) पर काम करता है।

0
जोड़ा