سؤال

أنا يمكن أن تفعل eval("something()"); إلى تنفيذ التعليمات البرمجية بشكل حيوي في جافا سكريبت.هل هناك طريقة بالنسبة لي أن تفعل الشيء نفسه في C# ؟

مثال ما أحاول القيام به هو:لدي متغير عدد صحيح (يقول i) ولقد خصائص متعددة من الأسماء:"Property1", "Property2", "Property3" ، الخ.الآن, أريد أن تنفيذ بعض العمليات على " الملكيةأنا "الملكية اعتمادا على قيمة i.

هذا هو حقا بسيطة مع جافا سكريبت.هل هناك أي طريقة للقيام بذلك مع C# ؟

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

المحلول

للأسف, C# ليست لغة ديناميكية مثل ذلك.

ما يمكنك القيام به ، ومع ذلك ، هو خلق C# كود المصدر ملف كامل مع فئة و كل شيء و تشغيله من خلال CodeDom مزود C# و ترجمة ذلك إلى الجمعية ، ومن ثم تنفيذ ذلك.

هذا منتدى آخر على MSDN يحتوي على إجابة مع بعض رمز المثال أسفل الصفحة إلى حد ما:
إنشاء طريقة مجهول من سلسلة ؟

أنا لا أقول هذا هو حل جيد جدا, ولكن من الممكن على أي حال.

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


تحرير:حسنا, أن يعلم مني أن أقرأ الأسئلة جيدا أولا.نعم, انعكاس سوف تكون قادرة على إعطائك بعض المساعدة هنا.

إذا كنت تقسيم السلسلة من قبل ؛ أولا للحصول على الخصائص الفردية, يمكنك استخدام التعليمات البرمجية التالية إلى الحصول على كائن PropertyInfo خاصية معينة لفئة ، ومن ثم استخدام هذا الكائن التعامل مع كائن معين.

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

الرابط: PropertyInfo.SetValue طريقة

نصائح أخرى

باستخدام روزلين البرمجة 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();");

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

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

هذا هو eval وظيفة تحت c#.أنا استخدامها لتحويل وظائف مجهولة (تعبيرات لامدا) من سلسلة.المصدر: 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;

}

كنت قد كتبت مشروع مفتوح المصدر ، ديناميكية Expresso, التي يمكن تحويل النص التعبير الكتابي باستخدام C# بناء الجملة في الوفود (أو شجرة التعبير).تعبيرات يتم تحليلها وتحويلها إلى أشجار التعبير دون استخدام تجميع أو التفكير.

يمكنك كتابة شيء من هذا القبيل:

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

عملي يعتمد سكوت قو المادة http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx .

كل ذلك بالتأكيد العمل.شخصيا لتلك المشكلة ، ربما تأخذ نهجا مختلفا قليلا.ربما شيء من هذا القبيل:

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

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

أدركت أن ليس السؤال, ولكن السؤال كان جيدا أجاب ظننت نهج بديل قد تساعد.

لا الآن إذا كنت على الاطلاق ترغب في تنفيذ C# البيانات ، ولكن يمكنك بالفعل تنفيذ جافا سكريبت البيانات في C# 2.0.مفتوحة المصدر مكتبة Jint هي قادرة على القيام بذلك.انها جافا سكريبت مترجم .صافي.اجتياز برنامج جافا سكريبت وأنه سيتم تشغيل داخل التطبيق الخاص بك.حتى يمكنك تمرير C# object كما الحجج و لا الآلي على ذلك.

أيضا إذا كنت ترغب فقط في تقييم التعبير على الممتلكات الخاصة بك, إعطاء محاولة NCalc.

يمكنك استخدام انعكاس للحصول على العقار و الاحتجاج بها.شيء من هذا القبيل:

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

هذا على افتراض الكائن الذي يحتوي على خاصية تسمى "الكائن" :)

يمكنك أيضا أن تنفيذ Webbrowser ، ثم تحميل ملف html اللي تبونه يحتوي على جافا سكريبت.

ثم u الذهاب document.InvokeScript الطريقة على هذا المتصفح.القيمة المرجعة من الدالة eval يمكن catched وتحويلها إلى كل ما تحتاجه.

أنا فعلت هذا في عدة مشاريع وأنها تعمل تماما.

آمل أن يساعد

يمكنك أن تفعل ذلك مع وظيفة النموذج:

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

وهلم جرا...

يستخدم انعكاس تحليل وتقييم البيانات ملزمة التعبير ضد كائن في وقت التشغيل.

DataBinder.Eval طريقة

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

على سبيل المثال ،

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

عودة 3;

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

بإرجاع كائن سياق سلسلة التمثيل ؛

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

يدير تلك التصريحات في البرنامج النصي, الخ.

التنفيذية يمكن أن تكون حصلت بسهولة باستخدام طريقة مصنع ، كما رأينا في المثال هنا- كل ما عليك هو مصدر رمز القائمة من أي المتوقعة اسمه المعلمات (الرموز المضمنة باستخدام الثلاثي قوس التدوين ، مثل {{{0}}}, لتجنب التصادم مع سلسلة.شكل() وكذلك المقاود-مثل جمل):

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

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

النفقات العامة المنفذة بالفعل جمعت النصي أو بيان منخفضة نسبيا ، في أقل من جزء من الثانية متواضعا من الأجهزة ، وبالفعل جمعت النصوص والعبارات مؤقتا لإعادة استخدامها.

كنت أحاول الحصول على قيمة الهيكل (الطبقة) عضو قبل تسميته.هيكل لم يكن ديناميكية.جميع الإجابات لم ينجح حتى حصلت أخيرا:

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

هذا الأسلوب بإرجاع قيمة من الأعضاء قبل تسميته.يعمل على العادية هيكل (الطبقة).

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

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

أو إذا كان عدد من الخصائص ليست لا نهاية لها ، يمكنك توليد واضعي chache لهم (المحددات أسرع لأنها جمعت المندوبين):

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

واضعي يمكن أن يكون من نوع Action<object, object> ولكن الحالات يمكن أن تكون مختلفة في وقت التشغيل ، بحيث يمكنك إنشاء قوائم من المحددات.

للأسف, C# لا يملك أي مواطن مرافق تفعل بالضبط ما كنت طالبا.

ومع ذلك ، C# eval البرنامج لا تسمح لتقييم التعليمات البرمجية C#.ويوفر تقييم C# كود في وقت التشغيل و يدعم العديد من C# البيانات.في الواقع, هذا الرمز يمكن استخدامها داخل أي .صافي المشروع ، ومع ذلك ، فإنه يقتصر على استخدام C# بناء الجملة.إلقاء نظرة على موقع الويب الخاص بي ، http://csharp-eval.com, ، للحصول على تفاصيل إضافية.

الإجابة الصحيحة هي تحتاج إلى ذاكرة التخزين المؤقت نتيجة للحفاظ على mem0ry الاستخدام المنخفض.

على سبيل مثال سوف تبدو مثل هذا

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

وإضافته إلى قائمة

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

حفظ معرف في قانون

ويساعد هذا الأمل

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