15

是否可以将字符串转换为运算符以用于逻辑条件。

例如

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()

这就是所有需要结合在一起的地方。

编辑:

好的,所以我从来没有看过 Lambdas 或 Expressions,我想我会关注@jrista 的建议。

我的系统允许解析枚举,因此表达式很有吸引力,因为表达式类型枚举。

所以我创建了以下类来测试这个想法:

    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"/>
4

9 回答 9

13

你可以这样做:

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;
 }
}
于 2009-05-29T14:08:50.013 回答
6

编辑

正如 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();
    }
}
于 2009-05-29T13:19:37.743 回答
4

不,这是不可能的,你为什么要这么做?

当然,您可以创建如下函数:

 public static bool Compare<T>(char op, T a, T b);
于 2009-05-29T13:16:40.620 回答
3

您应该考虑使用 .NET 3.5 的表达式树。您可以手动将表达式构建到表达式树(基本上是 AST)中,然后调用 Expression.Compile() 来创建可调用委托。您的 LogicRule.Test() 方法需要构建表达式树,将树包装在 LambdaExpression 中,LambdaExpression 将您应用规则的对象也作为参数,调用 Compile(),并调用生成的委托。

于 2009-05-29T16:47:34.740 回答
2

我在以下帮助下做了类似的事情:

http://flee.codeplex.com/

该工具基本上可以评估各种表达式。基本用法是传入一个像“3 > 4”这样的字符串,该工具将返回 false。

但是,您也可以创建评估器的实例并传入对象名称/值对,它可以更直观一点 IE:myObject^7 < yourObject.

您可以在 codeplex 站点深入了解更多功能。

于 2009-05-29T16:39:54.890 回答
0
<Function = "PredicateMore" Param1 = "Object1.Value" Param2 = "0"/>
于 2009-05-29T13:44:31.060 回答
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.
于 2009-05-29T14:52:00.037 回答
0

Vici Parser(开源)可能对您有所帮助。这是一个 C# 表达式解析器,您可以在其中传递一个包含表达式的字符串,然后返回计算结果。

于 2009-06-01T14:15:10.797 回答
0

您可以为此使用 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();
}
于 2021-05-13T16:08:54.887 回答