2009-05-29 21 views
12

È possibile convertire una stringa in un operatore per l'utilizzo in una condizione logica.C# converte una stringa per l'uso in una condizione logica

Per esempio

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

o

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

Mi rendo conto che questo potrebbe non essere questione pratica standard, perciò io non sono interessato a risposte che mi chiedono perché l'inferno vorrebbe fare qualcosa come questo.

Grazie in anticipo

EDIT: OK Sono d'accordo, giusto per dare qualche contesto.

Abbiamo un sistema basato su reflection e XML. Mi piacerebbe poter dire qualcosa del genere, per facilità.

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

EDIT: Grazie per i vostri commenti, non riesco a spiegarlo correttamente qui. Credo che alla mia domanda sia risposto "Non puoi", che è assolutamente soddisfacente (e cosa pensavo). Grazie per i tuoi commenti

EDIT: Sodd, sto per iniziare.

Immaginate la seguente

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

questo otterrà riflessa in una classe, in modo da ora voglio testare la condizione, chiamando

bool LogicRule.Test() 

Questo è il pezzo in cui tutto sarebbe bisogno di venire insieme.

EDIT:

OK, quindi non avendo mai guardato Lambda Expressions o ho pensato di dare un'occhiata dopo @ di jrista suggerimenti.

Il mio sistema consente di analizzare l'enumerazione, quindi le espressioni sono interessanti a causa dell'ExpressionType Enum.

così ho creato la seguente classe di testare l'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)); 

     } 
    } 

Ovviamente questo funziona solo per Int32 in questo momento e le ExpressionTypes di base, io non sono sicuro che posso farlo generica? Non ho mai usato le espressioni prima, tuttavia questo sembra funzionare.

In questo modo può quindi essere dichiarato nel nostro modo XML come

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

Non risponderò "perché stai facendo questo" ma lo commenterò invece :). Non sto cercando di essere un dolore, sono solo curioso di sapere perché questo è importante per la tua applicazione. – JaredPar

+1

@JaredPar: lo vedo sempre: persone che vogliono archiviarlo in un db e recuperarlo per usarlo nel codice più tardi. Non significa che sia una buona idea, ma è da lì che viene. –

+0

Grazie per l'aggiornamento, ma cosa vuoi fare con quell'XML e cosa significa? Vuoi avere quell'esempio in un elemento, "q", e fai "if (Compare (q, x))" per confrontare la variabile "x" in base alla condizione espressa nell'elemento XML? –

risposta

11

Si potrebbe fare qualcosa di simile:

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, non è possibile, e perché il diavolo si wnat per fare questo?

Si potrebbe, naturalmente, creare una funzione simile:

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

L'operazione "op" potrebbe richiedere più di un carattere; puoi avere "! =" o "<>" o "==" come potenziali operatori. –

5

EDIT

Come JaredPar ha sottolineato, il mio suggerimento di seguito non funzionerà come non è possibile applicare agli operatori di generics ...

Così avresti bisogno di avere implementazioni specifiche per ogni tipo si voleva confrontare/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

Si potrebbe fare qualcosa di simile.

Dovresti anche provare/catturare tutto ciò per garantire che qualsiasi T sia, supporta le operazioni particolari.

Mente se chiedo il motivo per cui è necessario farlo. Stai scrivendo una specie di parser matematico?

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

Sta andando a compilare? Io non la penso così –

+0

Questo è un approccio molto limitato. Al di fuori di == e! = Non puoi usare operatori su valori generici. – JaredPar

+0

@John, probabilmente no, l'ho scribacchiato direttamente nella finestra SO in modo che sia semi-pseudo @ Jared. Veramente ? ok ... gratta quell'idea ... :( –

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

penso che si può ottenere esattamente ciò utilizzando implicit casting. Qualcosa di simile:

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

che ho fatto qualcosa di simile a questo con l'aiuto di:

http://flee.codeplex.com/

Questo strumento può essenzialmente evaulate una vasta gamma di espressioni. L'utilizzo di base sarebbe passare una stringa come "3> 4" e lo strumento restituirebbe falso.

Tuttavia, è anche possibile creare un'istanza del programma di valutazione e passare le coppie nome/valore dell'oggetto e può essere un po 'più intuitivo IE: myObject^7 < yourObject.

C'è una tonnellata di funzionalità in più che puoi immergerti nel sito di codeplex.

3

Si dovrebbe esaminare utilizzando gli alberi di espressione di .NET 3.5. È possibile creare manualmente le espressioni in un albero di espressioni (in pratica un AST), quindi chiamare Expression.Compile() per creare un delegato chiamabile. Il tuo metodo LogicRule.Test() dovrebbe creare l'albero delle espressioni, avvolgere l'albero in una LambdaExpression che prende l'oggetto e applicare le regole come argomento, chiama Compile() e richiama il delegato risultante.

0

Vici Parser (open-source) può essere di aiuto. È un parser di espressioni C# in cui puoi semplicemente passare una stringa contenente un'espressione e ottenere il risultato calcolato.

Problemi correlati