首先,我在.Net方面经验不足,尤其是在过去的7年中。
我正在尝试开发应用程序,并希望合并另一个库(https://github.com/Giorgi/Math-Expression-Evaluator)
该库允许我评估诸如Evaluate("a+b", a: 1,b: 1)
之类的数学表达式。方法签名为public decimal Evaluate(string expression, object argument = null)
我真的只是在寻找文档和更多信息的指针。
编辑:对不起..故意将其保留得很宽泛,因为我不是在找人为我做我的工作..似乎无法找到开展我自己的研究的起点。
该方法称为
dynamic engine = new ExpressionEvaluator() ;
engine.Evaluate("(c+b)*a", a: 6, b: 4.5, c: 2.6)) ;
该代码在Evalute()主体中(它将该参数转换为字符串字典,十进制对)。
if (argument == null)
{
return new Dictionary<string, decimal>();
}
var argumentType = argument.GetType();
var properties = argumentType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead && IsNumeric(p.PropertyType));
var arguments = properties.ToDictionary(property => property.Name,
property => Convert.ToDecimal(property.GetValue(argument, null)));
return arguments;
我想做的是解析一个字符串,例如“a:1,b:2”,然后将其转换为与该
Evaluate()
签名匹配的对象。 最佳答案
那个图书馆正在使用高级魔法...非常高级:-)
诀窍是将该类声明为:
public class ExpressionEvaluator : DynamicObject
因此,这是一个实现.NET 4.0中引入的
dynamic
魔术的类现在...在该类中,有两种
Evaluate
方法:public decimal Evaluate(string expression, object argument = null)
和
private decimal Evaluate(string expression, Dictionary<string, decimal> arguments)
通常可见且可用的唯一方法是第一个。它的用法如下:
engine.Evaluate("a + b + c", new { a = 1, b = 2, c = 3 });
new { ... }
创建一个匿名对象,然后通过使用对Dictionary<string, decimal>
的反射将其“解包”给private Evaluate()
来将其解压缩。如果尝试使用另一种表示法,则该表示法如下:
engine.Evaluate("a + b + c", a: 1, b: 2, c: 3 });
然后.NET无法将该方法与存在的
public Evaluate()
进行匹配,但是该类是DynamicObject
的子类,导致C#编译器编写一些“魔术”代码来启动here方法(该表达式仍由ExpressionEvaluator实现) ):public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
首先检查我们要调用“评估”:
if (nameof(Evaluate) != binder.Name)
如果我们尝试调用Evaluate,它将参数解压缩为
new Dictionary<string, decimal>()
,然后调用private Evaluate()
。附带说明,要使用“动态”方式编写
Evaluate
,必须声明engine
变量,例如;dynamic dynamicEngine = new ExpressionEvaluator();
因此使用
dynamic
变量类型。现在...在编写库之后,您可以:
a
,b
和c
。不需要d
如果您未在编译时创建new { a, b, c, d }
,则在运行时)。例如,请参阅我三年前给出的this,它关于如何在运行时创建动态匿名类型。我给出该代码块的原因之一是:请注意,在对该响应的评论之一中,有一个指向我的代码的修改版本的链接,该链接由Dynamic.Linq的许多实现之一使用。
new Foo { a = 1, b = 2 c = 3 }
)。该库不区分匿名对象和非匿名对象。与以前一样的限制,因为在编译时,您需要一个带有正确数量的Foo
类dynamic
表示法。可悲的是,即使那是完全静态的。您不能轻易添加新参数,因为必须在编译时定义“变量”的数量和名称。 一个可能的解决方案是修改源代码(它是一个文件),并使
public
成为此方法:private decimal Evaluate(string expression, Dictionary<string, decimal> arguments)
那么您就可以轻松,动态地填充
Dictionary<string, decimal> arguments
关于c# - 在C#中动态创建数组的方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50722680/