我们需要在运行时评估对象中的值,同时我们有确切成员路径的文本语句,例如:myobject.firstMember.secondMember[3].text
我们考虑使用正则表达式解析此文本语句,然后评估文本通过使用反射来获得价值,但在我们这样做之前,我想知道 C# 是否支持某种eval能力?所以我们不必自己进行解析。微软如何在他们的即时窗口或监视窗口中执行此操作?
非常感谢你,
阿迪巴尔达
Probably the easiest way is to use DataBinder.Eval from System.Web.UI:
var foo = new Foo() { Bar = new Bar() { Value = "Value" } };
var value = DataBinder.Eval(foo, "Bar.Value");
我编写了一个开源项目Dynamic Expresso,它可以将使用 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);
我的工作基于 Scott Gu 的文章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
而不是直接反射,但是效果是一样的。
您可以随时尝试我的轻量级 C# Eval 程序。它将 C# 语言的大部分子集编译为动态方法。我的 GitHub 存储库DavidWynne/CSharpEval的完整详细信息
尽管是一种重量级的方法,但您可以使用 C# CodeDom 发出一个新的新程序集,其中包含仅使用该行代码的方法。
我承认,这比其他一些建议要严厉得多,但另一方面,你让 C# 解析器完成繁重的工作,所以只要它是有效的 C#,它应该能够处理你扔给它的所有东西.
如果您走这条路,您还需要确保可以再次卸载发出的程序集,因此可能需要创建和卸载 AppDomain。
我已经成功实现并使用了上述技术。另一方面,如果您可以使用DynamicMethod,它将更加轻量级。但是,我从未尝试过这种方法,所以我不能说您是否可以使用 C# 文字来实现 DynamicMethod 的主体。
实际上,Windows Workflow Foundation 的表达式评估和规则引擎功能可以做这样的事情。请参阅Windows Workflow Foundation 规则引擎简介。
关于这些组件的一个有趣的事情是,它们的设计目的是让您可以在自己的应用程序中托管设计时组件,以设计在您自己的自定义类的上下文中运行的规则和/或表达式集。例如,您会告诉它针对“myObject”设计一个表达式,它会知道有一个 firstMember 有一个 secondMember,它有一个索引器,产生一个具有 text 属性的类型。您可以将表达式和规则保存为 XML,并在运行时将它们读回,而无需在运行时使用设计器。
特别是,请参阅External RuleSet Toolkit Sample。
不幸的是,C# 没有任何本机工具可以完全按照您的要求进行操作。
但是,我的 C# eval 程序确实允许评估 C# 代码。它提供了在运行时评估 C# 代码并支持许多 C# 语句,包括像“ myobject.firstMember.secondMember[3].text ”这样的表达式。事实上,此代码可用于任何 .NET 项目,但仅限于使用 C# 语法。查看我的网站http://csharp-eval.com了解更多详细信息。
AFAIK 没有这样的内置 Eval 函数。您必须采用 Regex+Reflection 的方式。我也认为 Visual Studio 也在做同样的事情。
这是我用来查找动态嵌套属性的类似内容..您需要为索引器添加逻辑...以及一些额外的检查...我在调用方法中捕获了空值/错误...
public static object FindDottedProperty(this object input, string propertyName) { 如果(输入==空) 返回空值; if (string.IsNullOrEmpty(propertyName)) 返回空值; 队列道具 = new Queue(propertyName.Split('.')); if (props.Count == 0) 返回空值; //从输入对象开始并从那里推出属性堆栈。 对象 ret = 输入; while (props.Count > 0) { var prop = props.Dequeue(); if (string.IsNullOrEmpty(prop)) 返回空值; /*** 在此处添加索引器逻辑 ***/ //根据当前命名项获取属性值 ret = ret.GetType().GetProperty(prop).GetValue(ret, null); if (null.Equals(ret)) 返回空值; } //返回查找的值 返回 ret; }