如何在 C# (web) 中集中维护一个数学公式,以便在需要时对其进行更改?
Posted
技术标签:
【中文标题】如何在 C# (web) 中集中维护一个数学公式,以便在需要时对其进行更改?【英文标题】:How to centrally maintain a mathematical formula in C# (web) so it can be changed if needed? 【发布时间】:2013-01-05 12:50:58 【问题描述】:我们有一个应用程序在页面上有很多数学检查,根据它,用户会得到一个红绿灯(红、绿、黄)。
绿色 = 他可能会继续 红色 = 不要让他继续 黄色 = 允许继续但警告
这些公式作用于页面上的各种文本字段。因此,例如,如果 textbox1 有“10”而 texbox2 有“30”...公式可能是: T1 * T2 > 600 ? “绿色”:“红色”
我的问题是: 是否有可能以某种方式集中这些公式?
我为什么需要它? 现在,如果公式有任何更改,我们也必须在服务器端复制更改(违反 DRY,代码难以维护)
一种选择可能是 - 将(简单)公式存储为带有占位符的文本(?) - 用 javascript 和服务器端代码中的值替换占位符 - 在 JS 中使用 eval() 进行计算 - 在 C# 中使用 here 概述的技巧
在这种方法中,问题可能是 JS 和 C# 中相同数学字符串的不同解释。
我有道理还是应该报告这个问题?!! :P
【问题讨论】:
共享服务器逻辑和客户端逻辑是 Google Web Toolkit 试图解决的问题。 不要使用 eval,eval 很慢(而且很邪恶)!使用脚本插值和适当的缓存。 这通常是个难题。我建议不要改变公式。 :P 但说真的,您可能必须将公式作为字符串保存在数据库中并使用某种解析器。 我会检查GWT是否可以帮助我...... 如何创建一个业务规则类(服务器端),以便客户端 AJAX 在需要查找任何类型的响应时与之对话?所以基本上,数学检查只会存储在服务器端,而客户端只有代码,这些代码将发送到服务器进行所需的任何检查或验证。 【参考方案1】:根据您的应用程序的要求,只在服务器上进行所有验证可能是可以接受的。尤其是如果您的用户很少或大部分用户都在相当快的 Intranet 上,您可以“浪费”一些网络调用来省去维护上的麻烦。
如果用户想要在每个字段条目(或每隔几个条目,或每隔几秒)之间获得反馈,您可以使用 AJAX 调用请求服务器进行验证,而无需刷新整个页面。
这当然会导致比完全在客户端进行验证更多的请求,并且如果您的许多用户的网络连接不良,则在向他们提供反馈时可能会有延迟。我的猜测是总带宽使用量大致相同。您在每次验证往返时都使用一些,但这些都很小。您不会发送给客户端的所有验证 JS 可能会超过它。
主要好处是维护和 FUD,否则您可以保持客户端和服务器验证同步。无需编写验证 javascript 也可以节省时间。
在任何情况下,都值得退后一步,问问你的要求是什么。
【讨论】:
我的 JS 被缓存,因为它在一个单独的文件中,所以(不幸的是)总带宽在这两种情况下都不相同。但我仍然认为,按照你(和@DennisRongo)建议的方式,将来我的工作会更轻松。 我尝试过的其他事情:-@StefanSieber 建议的“表达”方式-结果对于我使用的公式来说非常复杂。 -@JordanDavidson 建议的逆波兰计算器-对于我的公式来说有点太复杂了【参考方案2】:Microsoft.CSharp.CSharpCodeProvider 提供程序可以即时编译代码。具体见CompileAssemblyFromFile。
这将允许您在运行时从 web.config 执行代码;但是请谨慎使用。
【讨论】:
【参考方案3】:您可以编写 C# 类来使用诸如 Expression、Value、BooleanExpr 等类(抽象语法树)对表达式建模
例如
Expression resultExpression = new ValueOf("T1").Times(new ValueOf("T2")).GreaterThan(600).IfElse("RED","GREEN")
^Variable ^Variable ^Value=>BoolExpr ^(Value, Value) => Value
然后可以使用这些表达式在 C# 中进行评估并发出用于检查的 Java 脚本:
String result = resultExpression.bind("T1", 10).bind("T2",20).evaluate() //returns "RED"
String jsExpression resultExpression.toJavaScript // emits T1 * T2 > 600 ? "RED" : "GREEN"
【讨论】:
这个可以作为一个足够好的解决方案,尽管我必须在 UI 上用我的文本框的名称替换发出的 JS。我会试一试,然后告诉你。 如果您需要对文本框进行一些映射,您可以在评估时使用类似于 bind() 的解决方案。 --> resultExpression.toJavascript.bind("T1","nameOfT1").bind("T2","nameOfT2).Code【参考方案4】:您可以创建一个低级计算器类,该类使用字符串作为输入并将事物推送和弹出到堆栈中。查找“逆波兰计算器”。如果您使用的输入数量没有改变,这将是一种非常巧妙的方式来存储您的方程。您可以非常轻松地将它们存储在文本文件或配置文件中。
例如:
string Equation = "V1,V2,+";
string ParseThis = Equation.Replace("V1", "34").Replace("V2", "45");
foreach(string s in ParseThis.split(','))
if (s == "+")
val1 = stack.Pop();
val2 = stack.Pop();
return int.parse(val1) + int.Parse(val2);
else
stack.Push(s);
显然,使用不同的方程式会变得更加复杂,但它可以让您将方程式存储为任何您想要的字符串。
如果任何语法不正确,我们深表歉意,但这应该会让您朝着正确的方向前进。
【讨论】:
【参考方案5】:最简单的解决方案是在 C# 服务器端实现一次公式,并在进行更改时使用 AJAX 评估来自客户端的表达式。这可能会减慢页面速度。
如果您希望公式在客户端和服务器端评估但只编写一次,那么我认为您需要执行以下操作:
将公式提取到单独的类中 对于客户端: Compile the class to Javascript 调用 javascript 版本,传入来自 DOM 的值 使用公式的结果更新 DOM 对于服务器端: 调用公式类,传入表单数据中的值(或控件,如果这是网络表单) 使用公式的结果采取必要的行动.. 或者您也可以反过来,用 Javascript 编写公式,然后使用 a C# Javascript engine 在服务器端评估该代码。
正如其他一些答案所建议的那样,我不会花时间编写自定义表达式语言,或编写将 C# 转换为 Javascript 的代码。如我链接到的问题所示,这些已经存在。这会分散您对业务问题的注意力。我会找到一个适合并从其他人的工作中受益的现有解决方案。
【讨论】:
以上是关于如何在 C# (web) 中集中维护一个数学公式,以便在需要时对其进行更改?的主要内容,如果未能解决你的问题,请参考以下文章