[英]C# convert a string for use in a logical condition
是否可以将字符串转换为运算符以用于逻辑条件。
例如
if(x Convert.ToOperator(">") y) {}
要么
if(x ">" as Operator y){}
我很欣赏这可能不是标准的练习问题,因此我对问我为什么他妈的想要做这样的事情的答案不感兴趣。
提前致谢
编辑:好的,我同意,只是提供一些上下文是公平的。
我们有围绕反射和 XML 构建的系统。 为了方便起见,我希望能够说一些类似的话。
<Value = "Object1.Value" Operator = ">" Condition = "0"/>
编辑:感谢您的评论,我无法在这里正确解释这一点。 我想我的问题是“你不能”回答的,这绝对没问题(也是我的想法)。 感谢您的意见。
编辑:我要去试一试。
想象以下
<Namespace.LogicRule Value= "Object1.Value" Operator=">" Condition="0">
这将反映到一个类中,所以现在我想通过调用来测试条件
bool LogicRule.Test()
这就是所有需要结合在一起的地方。
编辑:
好的,所以从来没有看过 Lambda 或表达式,我想我会看看@jrista 的建议。
我的系统允许解析枚举,因此由于 ExpressionType 枚举,表达式很有吸引力。
所以我创建了以下类来测试这个想法:
public class Operation
{
private object _Right;
private object _Left;
private ExpressionType _ExpressionType;
private string _Type;
public object Left
{
get { return _Left; }
set { _Left = value; }
}
public object Right
{
get { return _Right; }
set { _Right = value; }
}
public string Type
{
get { return _Type; }
set { _Type = value; }
}
public ExpressionType ExpressionType
{
get { return _ExpressionType; }
set { _ExpressionType = value; }
}
public bool Evaluate()
{
var param = Expression.Parameter(typeof(int), "left");
var param2 = Expression.Parameter(typeof(int), "right");
Expression<Func<int, int, bool>> expression = Expression.Lambda<Func<int, int, bool>>(
Expression.MakeBinary(ExpressionType, param, param2), param, param2);
Func<int, int, bool> del = expression.Compile();
return del(Convert.ToInt32(Left), Convert.ToInt32(Right));
}
}
显然这现在只适用于 Int32 和基本的 ExpressionTypes,我不确定我能不能让它通用? 我以前从未使用过表达式,但这似乎有效。
然后可以在我们的 XML 方式中将这种方式声明为
Operation<Left="1" Right="2" ExpressionType="LessThan" Type="System.Int32"/>
你可以这样做:
public static bool Compare<T>(string op, T x, T y) where T:IComparable
{
switch(op)
{
case "==" : return x.CompareTo(y)==0;
case "!=" : return x.CompareTo(y)!=0;
case ">" : return x.CompareTo(y)>0;
case ">=" : return x.CompareTo(y)>=0;
case "<" : return x.CompareTo(y)<0;
case "<=" : return x.CompareTo(y)<=0;
}
}
编辑
正如 JaredPar 所指出的,我下面的建议不起作用,因为您不能将运算符应用于泛型......
所以你需要为你想要比较/计算的每种类型都有特定的实现......
public int Compute (int param1, int param2, string op)
{
switch(op)
{
case "+": return param1 + param2;
default: throw new NotImplementedException();
}
}
public double Compute (double param1, double param2, string op)
{
switch(op)
{
case "+": return param1 + param2;
default: throw new NotImplementedException();
}
}
原点
你可以做这样的事情。
您还需要尝试/捕获所有这些以确保无论 T 是什么,都支持特定的操作。
介意我问你为什么可能需要这样做。 你在写某种数学解析器吗?
public T Compute<T> (T param1, T param2, string op) where T : struct
{
switch(op)
{
case "+":
return param1 + param2;
default:
throw new NotImplementedException();
}
}
public bool Compare<T> (T param1, T param2, string op) where T : struct
{
switch (op)
{
case "==":
return param1 == param2;
default:
throw new NotImplementedException();
}
}
不,这是不可能的,你为什么要这样做?
当然,您可以创建一个函数,例如:
public static bool Compare<T>(char op, T a, T b);
您应该考虑使用 .NET 3.5 的表达式树。 您可以手动将表达式构建到表达式树(基本上是一个 AST)中,然后调用 Expression.Compile() 来创建一个可调用的委托。 您的 LogicRule.Test() 方法需要构建 Expression 树,将树包装在 LambdaExpression 中,该 LambdaExpression 将您也应用规则的对象作为参数,调用 Compile(),并调用生成的委托。
我在以下人员的帮助下做了类似的事情:
该工具基本上可以评估范围广泛的表达式。 基本用法是传入像“3 > 4”这样的字符串,该工具将返回 false。
但是,您也可以创建评估器的实例并传入对象名称/值对,它可以更直观一些 IE:myObject^7 < yourObject。
您可以在 codeplex 站点上深入了解更多功能。
您可以为此使用 DynamicLinq:
void Main()
{
var match = OpCompare(6, ">=", 4);
match.Dump();
}
private bool OpCompare<T>(T leftHand, string op, T rightHand)
{
return new List<T>() { leftHand }.AsQueryable().Where($"it {op} {rightHand}").Any();
}
<Function = "PredicateMore" Param1 = "Object1.Value" Param2 = "0"/>
我认为您可以使用隐式强制转换来实现这一点。 就像是:
public static implicit operator Operator(string op)
{
switch(op) {
case "==" :
return new EqualOperator();
...
}
}
Operator op = "<";
if( op.Compare(x,y) ) { ... }
//or whatever use syntax you want for Operator.
Vici Parser (开源)可能对您有所帮助。 它是一个 C# 表达式解析器,您可以在其中传递包含表达式的字符串,然后返回计算结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.