كيف يمكنني إقناع GroovyShell بالحفاظ على الحالة عبر مكالمات eval()؟

StackOverflow https://stackoverflow.com/questions/45582

سؤال

أحاول استخدام Groovy لإنشاء نص تفاعلي/وضع ماكرو لتطبيقي.التطبيق هو OSGi ولا يتم معرفة الكثير من المعلومات التي قد تحتاجها البرامج النصية مقدمًا.اعتقدت أنه يمكنني استخدام GroovyShell واستدعاء eval() عدة مرات لإلحاق مساحة الاسم باستمرار أثناء تحميل حزم OSGi.يحتفظ GroovyShell بحالة متغيرة عبر استدعاءات تقييم متعددة، ولكن ليس تعريفات الفئة أو الأساليب.

هدف:إنشاء فئة أساسية أثناء بدء التشغيل.أثناء تحميل حزم OSGi، قم بإنشاء فئات مشتقة حسب الحاجة.

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

المحلول 2

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

نصائح أخرى

لست متأكدًا مما تقصده بشأن الفئات المعلنة غير الموجودة بين عمليات التقييم، يعمل النصان التاليان كما هو متوقع عند تقييمهما واحدًا تلو الآخر:

class C {{println 'hi'}}
new C()

...

new C()

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

Class klass = this.getClass()
this.getMetaClass().getMethods().each {
  if (it.declaringClass.cachedClass == klass) {
    binding[it.name] = this.&"$it.name"
  }
}

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

String scriptText = ...
Script script = shell.parse(scriptText)
def returnValue = script.run()
Class klass = script.getClass()
script.getMetaClass().getMethods().each {
  if (it.declaringClass.cachedClass == klass) {
    shell.context[it.name] = this.&"$it.name"
  }
}
// do whatever with returnValue...

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

قد يكون هذا ما تبحث عنه؟

من رائع في العمل

def binding = new Binding(x: 6, y: 4)
def shell = new GroovyShell(binding)
def expression = '''f = x * y'''
shell.evaluate(expression)
assert binding.getVariable("f") == 24

الاستخدام المناسب لـ Binding سيسمح لك بالحفاظ على الحالة؟

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