2009-05-29 10 views
12

¿Es posible convertir una cadena a un operador para su uso en una condición lógica.C# convierte una cadena para su uso en una condición lógica

Por ejemplo

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

o

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

Soy consciente de que esto podría no ser cuestión práctica estándar, por lo tanto, no estoy interesado en las respuestas que me pregunta por qué diablos querría hacer algo como esto.

Gracias de antemano

EDIT: OK estoy de acuerdo, lo justo para dar un poco de contexto.

Tenemos un sistema basado en reflexión y XML. Me gustaría poder decir algo como, por gusto.

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

EDIT: Gracias por sus comentarios, no puedo explicar esto correctamente aquí. Supongo que mi pregunta es respondida por "No se puede", lo cual está absolutamente bien (y lo que pensé). Gracias por tus comentarios.

EDIT: Sod it voy a tener una oportunidad.

Imagine la siguiente

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

Esto hará que se refleja en una clase, por lo que ahora quiero poner a prueba la condición, llamando

bool LogicRule.Test() 

Esa es la parte en la que todo iba a necesitar para llegar juntos.

EDIT:

OK, por lo que nunca tras mirar Lambdas o expresiones pensé que iba a tener una mirada después de sugerencias de @ jrista.

Mi sistema permite el análisis de Enumeraciones, por lo que las expresiones son atractivas debido a ExpressionType Enum.

así que creé la siguiente clase para probar la 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)); 

     } 
    } 

Obviamente esto sólo funcionará para Int32 en este momento y los ExpressionTypes básicas, no estoy seguro de que puedo hacerlo genérico? Nunca utilicé expresiones antes, sin embargo, esto parece funcionar.

De esta manera puede entonces ser declarada en nuestro camino XML como

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

No responderé "¿por qué estás haciendo esto?", Pero lo comentaré en su lugar :). No estoy tratando de ser un dolor, solo tengo curiosidad de por qué esto es importante para su aplicación. – JaredPar

+1

@JaredPar: Veo esto todo el tiempo: personas que desean almacenarlo en un archivo db y recuperarlo para utilizarlo en el código más adelante. No significa que sea una buena idea, pero de ahí viene. –

+0

Gracias por la actualización, pero ¿qué quiere hacer con ese XML y qué significa? ¿Desea tener ese ejemplo en un elemento, "q", y hacer "if (Compare (q, x))" para comparar la variable "x" de acuerdo con la condición expresada en el elemento XML? –

Respuesta

11

se podría hacer algo como esto:

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

No, no es posible, y por qué diablos se wnat para hacer esto?

Se podría, por supuesto, crear una función como:

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

El "op" podría necesitar ser más que un char; puede tener "! =" o "<>" o "==" como potenciales operadores. –

5

EDITAR

Como JaredPar señaló, mi sugerencia a continuación no funcionará como no se puede aplicar a los operadores genéricos ...

Así que había necesidad de disponer de implementaciones específicas para cada uno de los tipos que querían comparar/Calcular ...

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

Se podría hacer algo como esto.

También necesitaría probar/capturar todo esto para asegurarse de que sea lo que sea T, sea compatible con las operaciones particulares.

importa si te pregunto por qué es posible que tengas que hacer esto. ¿Estás escribiendo algún tipo de analizador matemático?

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

¿Eso va a compilar? No lo creo. –

+0

Sin embargo, este es un enfoque muy limitado. Fuera de == y! = No puede usar operadores en valores genéricos. – JaredPar

+0

@John, probablemente no, lo garabateé directamente en la ventana SO así que es semi-pseudo @Jared. De Verdad ? ok ... rasca esa Idea ... :( –

0
<Function = "PredicateMore" Param1 = "Object1.Value" Param2 = "0"/> 
0

Creo que se puede lograr exactamente esto utilizando implicit casting. Algo así como:

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. 
2

que he hecho algo similar a esto con la ayuda de:

http://flee.codeplex.com/

Esta herramienta puede esencialmente evaulate una amplia gama de expresiones. El uso básico sería pasar una cadena como '3> 4' y la herramienta devolvería falsa.

Sin embargo, también puede crear una instancia del evaluador y pasar pares de nombre/valor de objeto y puede ser un poco más intuitivo IE: myObject^7 < yourObject.

Hay una tonelada más de funcionalidad que puede encontrar en el sitio codeplex.

3

Debería considerar el uso de árboles de Expresión de .NET 3.5. Puede crear expresiones manualmente en un árbol de expresiones (básicamente un AST) y luego llamar a Expression.Compile() para crear un delegado invocable. Su método LogicRule.Test() necesitaría construir el árbol de Expresión, envolver el árbol en un LambdaExpression que toma al objeto su aplicación de las reglas también como un argumento, llama a Compilar() e invoca al delegado resultante.

0

Vici Parser (de código abierto) puede ser de ayuda para usted. Es un analizador de expresiones C# donde puedes pasar una cadena que contiene una expresión y obtienes el resultado calculado.

Cuestiones relacionadas