c# - C#中动态创建数组的方法

标签 c# .net scripting

首先,我在 .Net 方面没有太多经验 - 特别是在过去 7 年中。

我正在尝试开发一个应用程序,并希望合并另一个库 ( https://github.com/Giorgi/Math-Expression-Evaluator )

那个库允许我计算像 Evaluate("a+b", a: 1,b: 1) 这样的数学表达式.方法签名是 public decimal Evaluate(string expression, object argument = null)

  1. 我想更好地理解 .Net 如何将逗号分隔的参数转换为单个“参数”。
  2. 我不确定如何动态创建该参数。例如,遍历一个值列表并创建一个与该签名的适当参数相匹配的对象。

我真的只是在寻找文档和更多信息的指针。谢谢你的帮助。

编辑:抱歉..故意让它宽泛,因为我不是在找人为我做我的工作..似乎找不到做我自己研究的起点。

方法的调用方式是

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

所以它是一个实现 dynamic 的类.NET 4.0 中引入的魔法

现在...类(class)里有两个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 { ... }创建一个匿名对象,然后“解压”here通过对 Dictionary<string, decimal> 的反射使用被喂给private Evaluate() .

如果您尝试使用其他表示法,例如:

engine.Evaluate("a + b + c", a: 1, b: 2, c: 3 });

然后 .NET 无法将方法与 public Evaluate() 匹配存在,但是该类是 DynamicObject 的子类, 导致 C# 编译器编写一些启动 this 的“魔法”代码方法(仍然由 ExpressionEvaluator 实现):

public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)

首先检查我们要调用 Evaluate:

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 }。参见例如 response三年前我曾介绍过如何在运行时创建动态匿名类型。我给出该代码块的原因之一是:

    there are parts of the .NET framework that heavily use reflection to render objects (for example all the various datagrids). These parts are incompatible with dynamic objects and often don't support object[]. A solution is often to encapsulate the data in a DataTable... or you can use 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/

相关文章:

c# - C# 中的/= 运算符有什么作用?

string - 如何在 shell 脚本中删除字符串的子字符串?

javascript - 如何编写 Photoshop JavaScript 脚本将 PSD 文件中的所有图层复制到新文档?

c# - 从 Powershell 调用的 DLL 的当前目录错误

c# - 在 C# Process.Start 参数中使用单引号

c# - 尝试将我的模型转换为 IEnumerable<Model>

c# - RESTful 服务基本身份验证

c# - 传递依赖导致同一 DLL 的版本冲突

.net 编译器错误 “Not all code paths return a value” 上的任务方法

bash - 防止显示键入的字符(例如在 termios 中禁用 "echo"属性)