Ответ 1
Вероятно, самый простой способ - использовать DataBinder.Eval из System.Web.UI:
var foo = new Foo() { Bar = new Bar() { Value = "Value" } };
var value = DataBinder.Eval(foo, "Bar.Value");
нам нужно оценить значение в объекте во время выполнения, тогда как у нас есть текстовый оператор точного пути элемента, например: myobject.firstMember.secondMember [3].text
мы подумали о разборе этого текстового выражения с использованием регулярного выражения, а затем оценить текстовое значение с помощью отражения, но прежде чем мы это сделаем, я задаюсь вопросом, поддерживает ли С# какую-либо способность eval? поэтому нам не нужно будет разбираться. Как microsoft делает это в своем непосредственном окне или в окнах просмотра?
Большое спасибо,
Ади Барда
Вероятно, самый простой способ - использовать DataBinder.Eval из System.Web.UI:
var foo = new Foo() { Bar = new Bar() { Value = "Value" } };
var value = DataBinder.Eval(foo, "Bar.Value");
Я написал проект с открытым исходным кодом 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.
В будущем (около 5.0 таймфрейма) "компилятор как услуга" может это сделать. На самом деле, вы можете сделать многое из этого сейчас с помощью "mono" (см. CsharpRepl и Mono.CSharp - однако я ожидаю, что ему нужно будет узнать намного больше о контексте, чтобы иметь возможность использовать локальные переменные и т.д. в Evaluate
), но в текущем выпуске MS.NET поддержки нет.
На данный момент вам нужно будет сделать что-то вроде того, что делает много кода привязки данных... разделить его на токены, такие как ".". и использовать отражение. Строго говоря, код привязки фактически использует TypeDescriptor
/PropertyDescriptor
вместо прямого отражения, но эффект тот же.
К сожалению, у С# нет каких-либо родных средств для выполнения именно того, что вы просите.
Однако моя программа С# eval позволяет оценивать код С#. Он обеспечивает оценку кода С# во время выполнения и поддерживает множество операторов С#, включая выражения типа " myobject.firstMember.secondMember [3].text". Фактически, этот код можно использовать в любом .NET-проекте, однако он ограничен синтаксисом С#. Подробнее см. на моем веб-сайте http://csharp-eval.com.
Несмотря на несколько тяжелый подход, вы можете использовать С# CodeDom для создания новой новой сборки, содержащей метод только с этой строкой кода.
Это гораздо более тяжело, чем некоторые другие предложения, я признаю, но, с другой стороны, вы позволяете парсеру С# делать тяжелый подъем, поэтому он должен иметь возможность обрабатывать все, что вы бросаете на него, пока это действительно С#.
Если вы идете по этому маршруту, вам также необходимо убедиться, что вы можете снова выгрузить испущенную сборку, поэтому может потребоваться создание и разгрузка AppDomains.
Я успешно реализовал и использовал вышеупомянутую технику. С другой стороны, если вы можете использовать DynamicMethod, он будет гораздо более легким. Тем не менее, я никогда не пробовал этот подход, поэтому не могу сказать, можно ли реализовать тело DynamicMethod с использованием литералов С#.
На самом деле, функция моделирования выражений и правил для Windows Workflow Foundation может делать такие вещи. См. Введение в механизм правил Windows Workflow Foundation.
Интересной особенностью этих компонентов является то, что они были разработаны таким образом, что вы можете размещать компоненты времени разработки в своих приложениях для разработки наборов правил и/или выражений, которые работают в контексте ваших собственных пользовательских классов. Например, вы сказали бы, чтобы он разработал выражение против "myObject", и он знал бы, что есть первый член, у которого есть второй член, у которого есть индекс, дающий тип, который имеет свойство text. Вы можете сохранять выражения и правила как XML и читать их во время выполнения, без необходимости использовать конструктор во время выполнения.
В частности, см. Внешний пример набора инструментов RuleSet.
Вы всегда можете попробовать мою легкую программу С# Eval. Он компилирует существенное подмножество языка С# для динамических методов. Полная информация на моем сайте KamimuCode.Com
AFAIK нет такой встроенной функции Eval. Вам нужно будет пойти по пути Regex + Reflection. Я также думаю, что Visual Studio делает то же самое.
Здесь что-то подобное я использую, чтобы найти динамически вложенные свойства.. вам нужно добавить логику для индексаторов... и некоторую дополнительную проверку... Я улавливаю 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; }