Вопрос

На этот вопрос уже есть ответ здесь:

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

большое вам спасибо,

Ади Барда

Это было полезно?

Решение

Вероятно, самый простой способ - это использовать Привязчик данных.Оценка из System.Web.UI:

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

Другие советы

Я написал проект с открытым исходным кодом, Динамичный Эспрессо, который может преобразовывать текстовое выражение, написанное с использованием синтаксиса 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 .

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

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

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

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

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

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

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

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

В частности, смотрите Пример набора инструментов для внешнего набора правил.

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

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

Вы всегда можете попробовать мою облегченную программу C # Eval.Он компилирует значительное подмножество языка C # в динамические методы.Полная информация в моем репозитории GitHub Дэвид Уинн/CSharpEval

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

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

  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's 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;
  }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top