سؤال

هنا هو رمز تقييم تعبير بسيط للغاية باستخدام IronRuby

public class BasicRubyExpressionEvaluator
{
    ScriptEngine engine;
    ScriptScope scope;
    public Exception LastException
    {
        get; set;
    }
    private static readonly Dictionary<string, ScriptSource> parserCache = new Dictionary<string, ScriptSource>();
    public BasicRubyExpressionEvaluator()
    {
        engine = Ruby.CreateEngine();
        scope = engine.CreateScope();

    }

    public object Evaluate(string expression, DataRow context)
    {
        ScriptSource source;
        parserCache.TryGetValue(expression, out source);
        if (source == null)
        {
            source = engine.CreateScriptSourceFromString(expression, SourceCodeKind.SingleStatement);
            parserCache.Add(expression, source);
        }

        var result = source.Execute(scope);
        return result;
    }
    public void SetVariable(string variableName, object value)
    {
        scope.SetVariable(variableName, value);
    }
}

وهنا مشكلة.

var evaluator = new BasicRubyExpressionEvaluator();
evaluator.SetVariable("a", 10);
evaluator.SetVariable("b", 1 );
evaluator.Evaluate("a+b+2", null);

ضد

var evaluator = new BasicRubyExpressionEvaluator();
evaluator.Evaluate("10+1+2", null);

الاول هو 25 مرة أبطأ من الثانية. أي اقتراحات؟ string.replace ليس حلا بالنسبة لي.

هل كانت مفيدة؟

المحلول

لا أعتقد أن الأداء الذي تراه يرجع إلى إعداد متغير؛ سيكون التنفيذ الأول لأول مرة في برنامج أبطأ دائما من الثانية، بغض النظر عن ما تقوم به، لأن معظم المحول البرمجي لم يتم تحميله حتى يتم تشغيل التعليمات البرمجية فعليا (لأسباب أداء بدء التشغيل). يرجى تجربة ذلك المثال مرة أخرى، وربما تشغيل كل إصدار من التعليمات البرمجية الخاصة بك في حلقة، وسترى الأداء هو ما يعادل تقريبا؛ يحتوي الإصدار المتغير على بعض النفقات العامة لإرسال الأسلوب للحصول على المتغيرات، ولكن يجب أن يكون ذلك ضئيلا إذا قمت بتشغيله بما فيه الكفاية.

أيضا، في رمز الاستضافة الخاص بك، كيف تأتي أنت تمسك البرامج النصية في القاموس؟ وأود أن أمسك بالجوام (نتيجة للمحرك.خطأإخراجوسوسوسكورص (...). ترجمة ()) بدلا من ذلك - كما سيساعد ذلك كثيرا في تكرار التشغيل.

نصائح أخرى

يمكنك بالطبع أولا بناء السلسلة شيء مثل

Evaluator.evaly (String.format ("A = {0}؛ B = {1}؛ A + B + 2"، 10، 1))

أو يمكنك جعله طريقة

إذا بدلا من البرنامج النصي، فإنك ترجع طريقة، فعليك أن تكون قادرا على استخدامها ككائن C # العادي C #.

var script = @"

def self.addition(a, b)
  a + b + 2
end
"

engine.ExecuteScript(script);
var = func = scope.GetVariable<Func<object,object,object>>("addition");    
func(10,1)

ربما هذا ليس مقتطفا يعمل لكنه يدل على الفكرة العامة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top