Вопрос
На этот вопрос уже есть ответ здесь:
- Как я могу динамически оценивать код C #? 16 ответов
нам нужно вычислить значение в объекте во время выполнения, пока у нас есть текстовое указание точного пути к элементу, например: 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; }