2008-09-10 11 views
43

मैं के बराबर करना चाहते हैं: के बाद Biri रों linkमैं गतिशील रूप से सी # अभिव्यक्ति का मूल्यांकन कैसे कर सकता हूं?

object result = Eval("1 + 3"); 
string now = Eval("System.DateTime.Now().ToString()") as string 

, मैं इस स्निपेट (अप्रचलित विधि ICodeCompiler.CreateCompiler() दूर करने के लिए संशोधित मिला:

private object Eval(string sExpression) 
{ 
    CSharpCodeProvider c = new CSharpCodeProvider(); 
    CompilerParameters cp = new CompilerParameters(); 

    cp.ReferencedAssemblies.Add("system.dll"); 

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

    StringBuilder sb = new StringBuilder(""); 
    sb.Append("using System;\n"); 

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

    CompilerResults cr = c.CompileAssemblyFromSource(cp, sb.ToString()); 
    if (cr.Errors.Count > 0) 
    { 
     throw new InvalidExpressionException(
      string.Format("Error ({0}) evaluating: {1}", 
      cr.Errors[0].ErrorText, sExpression)); 
    } 

    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

यह आवश्यक क्यों है? मुझे बहुत संदेह है कि जो भी उद्देश्य आप चाहते हैं उसके लिए यह सबसे अच्छा डिजाइन है। संभावित रूप से अधिक संभावनाएं उत्पन्न करने के लिए अन्य तंत्र हैं जो आप चाहते हैं कि वेड़े की भारी मात्रा (सुरक्षा और रखरखाव के लिए) खोलने के बिना रन टाइम पर कोड स्निपेट का मूल्यांकन कर रहे हों। – Wedge

+0

मैंने लिखा एक डीएसएल को अभिव्यक्ति सत्यापन जोड़ने के लिए एक त्वरित और गंदा तरीका चाहता था। मैं मूल्यांकनकर्ता को खिलाया जा रहा फाइलों को नियंत्रित करता हूं, इसलिए कीड़े का खंभा कभी नहीं खोला जाता है;) इसके अलावा, मैं केवल एक अभिव्यक्ति की अनुमति देता हूं, किसी भी नामस्थान/किसी भी असेंबली को संदर्भित नहीं करता हूं। यह खुद को नुकसान पहुंचाने से रोकना चाहिए! –

+1

मैं परीक्षण परिदृश्य में ऐसा करता हूं। मेरे पास एक असेंबली है जो संस्करण संख्याओं को बदलती है क्योंकि इसे अपडेट किया जाता है। मैं चाहता हूं कि मेरा टेस्ट कोड असेंबली को "देर से बाध्य" हो - असेंबली लोड करने में सक्षम हो और गतिशील रूप से कॉल करें। यह प्रतिबिंब का एक साधारण मामला है। लेकिन जब मैं असेंबली में निर्दिष्ट इंटरफ़ेस को कार्यान्वित करना चाहता हूं, तो उसे कोड के गतिशील संकलन की आवश्यकता होती है, क्योंकि इंटरफ़ेस स्वयं दृढ़ता से नामित होता है (संस्करण संख्या के साथ)। मेरे पास कोड नहीं हो सकता है जो IFoo v1.2 लागू करता है जब मैं v1.3 का आह्वान करना चाहता हूं। गतिशील संकलन इस पते को संबोधित करता है। – Cheeso

उत्तर

32

मक्खी पर संकलन का उपयोग करके, जैसे this example शो।

या Flee का उपयोग, जो बिल्कुल एक ही कारण के लिए है से।

1

ऐसा करने के प्रदर्शन प्रभाव क्या हैं?

हम ऊपर उल्लिखित कुछ के आधार पर एक प्रणाली का उपयोग करते हैं, जहां प्रत्येक सी # स्क्रिप्ट को इन-मेमोरी असेंबली में संकलित किया जाता है और एक अलग ऐपडोमेन में निष्पादित किया जाता है। अभी तक कोई कैशिंग सिस्टम नहीं है, इसलिए जब भी वे दौड़ते हैं तो स्क्रिप्ट को फिर से सम्मिलित किया जाता है। मैंने कुछ सरल परीक्षण किया है और डिस्क से स्क्रिप्ट लोड करने सहित, मेरी मशीन पर लगभग 0.7 सेकंड में एक बहुत ही सरल "हैलो वर्ल्ड" स्क्रिप्ट संकलित है। 0.7 सेकंड एक स्क्रिप्टिंग सिस्टम के लिए ठीक है, लेकिन उपयोगकर्ता इनपुट के जवाब में बहुत धीमा हो सकता है, उस स्थिति में फ्ली जैसे समर्पित पार्सर/कंपाइलर बेहतर हो सकते हैं।

using System; 
public class Test 
{ 
    static public void DoStuff(Scripting.IJob Job) 
    { 
     Console.WriteLine("Heps"); 
    } 
} 
0

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

http://www.webtips.co.in/c/evaluate-function-in-c-net-as-eval-function-in-javascript.aspx

मैं इसे कोशिश करते हैं और बाद में बताती हैं कि यह काम किया जाएगा। मैं सिल्वरलाइट में इसे आजमाने का भी इरादा रखता हूं, लेकिन यह बहुत देर हो चुकी है और अब मैं इसे करने के लिए लगभग सो रहा हूं।

2
using System; 
using Microsoft.JScript; 
using Microsoft.JScript.Vsa; 
using Convert = Microsoft.JScript.Convert; 

namespace System 
{ 
    public class MathEvaluator : INeedEngine 
    { 
     private VsaEngine vsaEngine; 

     public virtual String Evaluate(string expr) 
     { 
      var engine = (INeedEngine)this; 
      var result = Eval.JScriptEvaluate(expr, engine.GetEngine()); 

      return Convert.ToString(result, true); 
     } 

     VsaEngine INeedEngine.GetEngine() 
     { 
      vsaEngine = vsaEngine ?? VsaEngine.CreateEngineWithType(this.GetType().TypeHandle); 
      return vsaEngine; 
     } 

     void INeedEngine.SetEngine(VsaEngine engine) 
     { 
      vsaEngine = engine; 
     } 
    } 
} 
+0

आयरन जेएस नामक एक बेहतर जावास्क्रिप्ट कार्यान्वयन है। इसने आयरन पायथन, आदि जैसे डीएलआर का उपयोग किया [नुगेट पर आयरन जेएस] (http://nuget.org/List/Packages/IronJS)। जैसा कि मैं समझता हूं कि वीएसए अप्रचलित है –

1

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

20

मैंने ओपन सोर्स प्रोजेक्ट, Dynamic Expresso लिखा है, जो प्रतिनिधियों (या अभिव्यक्ति वृक्ष) में सी # सिंटैक्स का उपयोग करके लिखी गई पाठ अभिव्यक्ति को परिवर्तित कर सकता है। संकलन या प्रतिबिंब का उपयोग किये बिना पाठ अभिव्यक्तियों को पार्स किया गया है और Expression Trees में बदल दिया गया है।

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

या

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

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

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

parsedExpression.Invoke(5); 

मेरा काम स्कॉट गु लेख http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx पर आधारित है:

आप की तरह कुछ लिख सकते हैं।

+0

+1 - मैंने इस परियोजना की कोशिश की ... शानदार! – pilotcam

+0

+1 @ डेविड लाइकार्डि यह बहुत अच्छी लाइब्रेरी है, लेकिन इसमें कुछ सीमाएं हैं: https://stackoverflow.com/questions/46581067/how-to-make-dynamicexpresso-recognizes-members-using- new-modifier – Dabbas

9

पुराना विषय, लेकिन यह विचार करते समय यह पहला धागा दिखा रहा है, यहां एक अद्यतन समाधान है।

आप Roslyn's new Scripting API to evaluate expressions का उपयोग कर सकते हैं।

यदि आप NuGet का उपयोग कर रहे हैं, तो बस Microsoft.CodeAnalysis.CSharp.Scripting पर निर्भरता जोड़ें। उदाहरण आपके द्वारा दी गई मूल्यांकन करने के लिए, यह उतना ही आसान है:

var result = CSharpScript.EvaluateAsync("1 + 3").Result; 

यह स्पष्ट रूप से स्क्रिप्टिंग इंजन के async क्षमताओं का उपयोग करना नहीं है।

आप भी मूल्यांकन परिणाम प्रकार आपकी इच्छानुसार निर्दिष्ट कर सकते हैं:

var now = CSharpScript.EvaluateAsync<string>("System.DateTime.Now.ToString()").Result; 

अधिक उन्नत कोड के टुकड़े का मूल्यांकन करने के लिए, पैरामीटर भेजने, संदर्भ, नामस्थान और whatnot प्रदान करते हैं विकि ऊपर लिंक की जाँच करें।

संबंधित मुद्दे