C# 转换字符串以用于逻辑条件

发布于 2024-07-21 07:36:17 字数 2387 浏览 6 评论 0原文

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

例如

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

This 将反映到一个类中,所以现在我想通过调用 That 来测试条件,

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

Is it possible to convert a string to an operator for use in a logical condition.

For example

if(x Convert.ToOperator(">") y) {}

or

if(x ">" as Operator y){}

I appreciate that this might not be standard practice question, therefore I'm not interested in answers that ask me why the hell would want to do something like this.

Thanks in advance

EDIT: OK I agree, only fair to give some context.

We have system built around reflection and XML. I would like to be able to say something like, for ease.

<Value = "Object1.Value" Operator = ">" Condition = "0"/>

EDIT: Thanks for your comments, I can't properly explain this on here. I guess my question is answered by "You can't", which is absolutely fine (and what I thought). Thanks for your comments.

EDIT: Sod it I'm going to have a go.

Imagine the following

<Namespace.LogicRule Value= "Object1.Value" Operator=">" Condition="0">  

This will get reflected into a class, so now I want to test the condition, by calling

bool LogicRule.Test()

That's the bit where it would all need to come together.

EDIT:

OK, so having never looked at Lambdas or Expressions I thought I would have a look after @jrista's suggestions.

My system allows Enums to be parsed, so Expressions are attractive because of the ExpressionType Enum.

So I created the following class to test the idea:

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

        }
    }

Obviously this will only work for Int32 right now and the basic ExpressionTypes, I'm not sure I can make it generic? I've never use Expressions before, however this seems to work.

This way can then be declared in our XML way as

Operation<Left="1" Right="2" ExpressionType="LessThan" Type="System.Int32"/>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

一个人的旅程 2024-07-28 07:36:17

你可以这样做:

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;
 }
}

You could do something like this:

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;
 }
}
━╋う一瞬間旳綻放 2024-07-28 07:36:17

编辑

正如 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();
    }
}

ORIG

你可以做这样的事情。

您还需要尝试/捕获所有这些,以确保无论 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();
    }
}

EDIT

As JaredPar pointed out, my suggestion below won't work as you can't apply the operators to generics...

So you'd need to have specific implementations for each types you wanted to compare/compute...

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

ORIG

You could do something like this.

You'd also need to try/catch all this to ensure that whatever T is, supports the particular operations.

Mind if I ask why you would possibly need to do this. Are you writing some sort of mathematical parser ?

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();
    }
}
递刀给你 2024-07-28 07:36:17

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

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

 public static bool Compare<T>(char op, T a, T b);

No, it's not possible, and why the hell would you wnat to do this?

You could, of course, create a function like:

 public static bool Compare<T>(char op, T a, T b);
暗藏城府 2024-07-28 07:36:17

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

You should look into using .NET 3.5's Expression trees. You can build expressions manually into an expression tree (basically an AST), and then call Expression.Compile() to create a callable delegate. Your LogicRule.Test() method would need to build the Expression tree, wrap the tree in a LambdaExpression that takes the object your applying the rules too as an argument, calls Compile(), and invokes the resulting delegate.

剪不断理还乱 2024-07-28 07:36:17

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

http://flee.codeplex.com/

该工具本质上可以评估各种表达式。 基本用法是传入一个类似 '3 > > 的字符串。 4' 并且该工具将返回 false。

但是,您也可以创建求值器的实例并传入对象名称/值对,这可以更直观一点 IE: myObject^7 < 你的对象。

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

I've done something similar to this with the help of:

http://flee.codeplex.com/

This tool can essentially evaulate a wide range of expressions. Basic usage would be to pass in a string like '3 > 4' and the tool would return false.

However, you can also create an instance of the evaluator and pass in object name/value pairs and it can be a little more intuitive IE: myObject^7 < yourObject.

There is a ton more functionality that you can dive into at the codeplex site.

撩发小公举 2024-07-28 07:36:17

您可以使用 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();
}

You can use DynamicLinq for this:

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(
quot;it {op} {rightHand}").Any();
}
咆哮 2024-07-28 07:36:17

我认为您可以使用 隐式转换。 就像是:

   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.

I think you can achieve exactly this using implicit casting. Something like:

   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.
独夜无伴 2024-07-28 07:36:17

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

Vici Parser (open-source) may be of help to you. It's a C# expression parser where you can just pass a string containing an expression, and you get the computed result back.

夜血缘 2024-07-28 07:36:17
<Function = "PredicateMore" Param1 = "Object1.Value" Param2 = "0"/>
<Function = "PredicateMore" Param1 = "Object1.Value" Param2 = "0"/>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文