Поддержка С# Eval()

нам нужно оценить значение в объекте во время выполнения, тогда как у нас есть текстовый оператор точного пути элемента, например: myobject.firstMember.secondMember [3].text
мы подумали о разборе этого текстового выражения с использованием регулярного выражения, а затем оценить текстовое значение с помощью отражения, но прежде чем мы это сделаем, я задаюсь вопросом, поддерживает ли С# какую-либо способность eval? поэтому нам не нужно будет разбираться. Как microsoft делает это в своем непосредственном окне или в окнах просмотра?

Большое спасибо,

Ади Барда

Ответы

Ответ 1

Вероятно, самый простой способ - использовать DataBinder.Eval из System.Web.UI:

var foo = new Foo() { Bar = new Bar() { Value = "Value" } };
var value = DataBinder.Eval(foo, "Bar.Value");

Ответ 2

Я написал проект с открытым исходным кодом 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.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.

Ответ 3

В будущем (около 5.0 таймфрейма) "компилятор как услуга" может это сделать. На самом деле, вы можете сделать многое из этого сейчас с помощью "mono" (см. CsharpRepl и Mono.CSharp - однако я ожидаю, что ему нужно будет узнать намного больше о контексте, чтобы иметь возможность использовать локальные переменные и т.д. в Evaluate), но в текущем выпуске MS.NET поддержки нет.

На данный момент вам нужно будет сделать что-то вроде того, что делает много кода привязки данных... разделить его на токены, такие как ".". и использовать отражение. Строго говоря, код привязки фактически использует TypeDescriptor/PropertyDescriptor вместо прямого отражения, но эффект тот же.

Ответ 4

К сожалению, у С# нет каких-либо родных средств для выполнения именно того, что вы просите.

Однако моя программа С# eval позволяет оценивать код С#. Он обеспечивает оценку кода С# во время выполнения и поддерживает множество операторов С#, включая выражения типа " myobject.firstMember.secondMember [3].text". Фактически, этот код можно использовать в любом .NET-проекте, однако он ограничен синтаксисом С#. Подробнее см. на моем веб-сайте http://csharp-eval.com.

Ответ 5

Несмотря на несколько тяжелый подход, вы можете использовать С# CodeDom для создания новой новой сборки, содержащей метод только с этой строкой кода.

Это гораздо более тяжело, чем некоторые другие предложения, я признаю, но, с другой стороны, вы позволяете парсеру С# делать тяжелый подъем, поэтому он должен иметь возможность обрабатывать все, что вы бросаете на него, пока это действительно С#.

Если вы идете по этому маршруту, вам также необходимо убедиться, что вы можете снова выгрузить испущенную сборку, поэтому может потребоваться создание и разгрузка AppDomains.

Я успешно реализовал и использовал вышеупомянутую технику. С другой стороны, если вы можете использовать DynamicMethod, он будет гораздо более легким. Тем не менее, я никогда не пробовал этот подход, поэтому не могу сказать, можно ли реализовать тело DynamicMethod с использованием литералов С#.

Ответ 6

На самом деле, функция моделирования выражений и правил для Windows Workflow Foundation может делать такие вещи. См. Введение в механизм правил Windows Workflow Foundation.

Интересной особенностью этих компонентов является то, что они были разработаны таким образом, что вы можете размещать компоненты времени разработки в своих приложениях для разработки наборов правил и/или выражений, которые работают в контексте ваших собственных пользовательских классов. Например, вы сказали бы, чтобы он разработал выражение против "myObject", и он знал бы, что есть первый член, у которого есть второй член, у которого есть индекс, дающий тип, который имеет свойство text. Вы можете сохранять выражения и правила как XML и читать их во время выполнения, без необходимости использовать конструктор во время выполнения.

В частности, см. Внешний пример набора инструментов RuleSet.

Ответ 7

Вы всегда можете попробовать мою легкую программу С# Eval. Он компилирует существенное подмножество языка С# для динамических методов. Полная информация на моем сайте KamimuCode.Com

Ответ 8

AFAIK нет такой встроенной функции Eval. Вам нужно будет пойти по пути Regex + Reflection. Я также думаю, что Visual Studio делает то же самое.

Ответ 9

Здесь что-то подобное я использую, чтобы найти динамически вложенные свойства.. вам нужно добавить логику для индексаторов... и некоторую дополнительную проверку... Я улавливаю nulls/errors в моем методе вызова...

  public static object FindDottedProperty(this object input, string propertyName)
  {
    if (input == null)
      return null;

    if (string.IsNullOrEmpty(propertyName))
      return null;

    Queue props = new Queue(propertyName.Split('.'));
    if (props.Count == 0) return null;

    //start with input object and roll out property stack from there.
    object ret = input;
    while (props.Count > 0)
    {
      var prop = props.Dequeue();
      if (string.IsNullOrEmpty(prop)) return null;

      /*** ADD INDEXER LOGIC HERE ***/

      //get the property value based on the current named item
      ret = ret.GetType().GetProperty(prop).GetValue(ret, null);

      if (null.Equals(ret)) return null;
    }

    //return looked up value
    return ret;
  }