Domanda

Ho bisogno di permettere ai miei utenti di essere in grado di definire le formule che calcolare i valori in base ai dati. Ad esempio

//Example 1
return GetMonetaryAmountFromDatabase("Amount due") * 1.2;
//Example 2
return GetMonetaryAmountFromDatabase("Amount due") * GetFactorFromDatabase("Discount");

I sarà necessario per consentire / * + - le operazioni, anche di assegnare variabili locali ed eseguire istruzioni IF, in questo modo

var amountDue = GetMonetaryAmountFromDatabase("Amount due");
if (amountDue > 100000) return amountDue * 0.75;
if (amountDue > 50000) return amountDue * 0.9;
return amountDue;

Lo scenario è complicato perché ho la seguente struttura ..

  1. Clienti (qualche centinaio)
  2. Configurazione (circa il 10 per cliente)
  3. Prodotto (circa 10.000 per la configurazione del cliente)

Così farò un ciclo di 3 livelli. Ad ogni livello "Configurazione" Inizierò una transazione DB e compilare i forumlas, ogni "voce" utilizzerà la stessa transazione + formule compilati (ci sono circa 20 formule per la configurazione, ogni elemento utilizzerà tutti loro).

Questo complica ulteriormente le cose perché non posso semplicemente utilizzare i servizi del compilatore in quanto si tradurrebbe in continua crescita l'utilizzo della memoria. Non posso usare un nuovo dominio di applicazione per ogni livello del ciclo "Configurazione", perché alcuni dei riferimenti ho bisogno di passare non può essere schierato.

Qualche suggerimento?

- Update-- Questo è quello che ho passato con, grazie! http://www.codeproject.com/Articles/53611/ Embedding-IronPython-in-aC-Application

È stato utile?

Soluzione

Si potrebbe creare una semplice classe in fase di esecuzione, semplicemente scrivendo la logica in una stringa o simili, compilarlo, eseguirlo e farlo tornare i calcoli necessari. In questo articolo vi mostra come accedere al compilatore di runtime: http: //www.codeproject. com / KB / cs / codecompilation.aspx

Altri suggerimenti

ironpython Consente di incorporare un motore di scripting nella vostra applicazione. Ci sono molte altre soluzioni. In realtà, si può google qualcosa come "C # scripting embedded" e trovare un sacco di opzioni. Alcuni sono più facili di altre per integrare, e alcuni sono più facili di altre al codice degli script.

Naturalmente, c'è sempre VBA. Ma questo è solo decisamente brutto.

Ho affrontato un problema simile a pochi anni fa. Ho avuto una web app con traffico moderato che doveva permettere equazioni, ed è necessario caratteristiche simili ai tuoi, e doveva essere veloce. Sono andato attraverso diverse idee.

La prima soluzione coinvolto l'aggiunta di colonne calcolate al nostro database. I nostri tavoli per l'App Store le proprietà di colonne (per esempio, c'è una colonna per importo dovuto, un altro sconto, ecc). Se l'utente ha digitato in una formula come PropertyA * 2, il codice altererebbe la tabella sottostante per avere una nuova colonna calcolata. E 'disordinato quanto riguarda l'aggiunta e la rimozione di colonne. Esso ha alcuni vantaggi però: il database (SQL Server) è stato molto veloce a fare i calcoli; il database gestito un sacco di rilevamento degli errori per noi; e ho potuto fingere che i valori calcolati erano gli stessi che i valori non calcolati, il che significava che io non ho dovuto modificare qualsiasi codice esistente che ha lavorato con i valori non calcolati.

che ha lavorato per un po 'finché non abbiamo bisogno la possibilità per una formula per fare riferimento un'altra formula, e SQL Server non consente questo. Quindi sono passato a un motore di scripting. IronPython non è stato molto maturo di allora, così ho scelto un altro motore ... non ricordo che uno proprio ora. Comunque, è stato facile da scrivere, ma era un po 'lento. Non molto, forse pochi millisecondi per query, ma per una web app momento veramente arricchito fino oltre tutte le richieste.

Questo è stato quando ho deciso di scrivere il mio parser per le formule. Cioè, ho una classe PlusToken per aggiungere due valori, una classe ItemToken che corrisponde a GetValue ( "sconto"), ecc Quando l'utente immette una nuova formula, un validatore analizza la formula, fa in modo che sia valido (cose come, l'hanno fatto riferimento a una colonna che non esiste?), e lo memorizza in una forma semi-compilato che è facile da analizzare in seguito. Quando l'utente richiede un valore calcolato, un parser legge la formula, lo analizza, figure quali dati è necessario dal database, e calcola la risposta finale. C'è voluto un bel po 'di lavoro in anticipo, ma funziona bene ed è veramente veloce. Ecco cosa ho imparato:

  1. Se l'utente immette una formula che porta a un ciclo nelle formule, e si tenta di calcolare il valore della formula, sarete a corto di spazio dello stack. Se si sta eseguendo questo su una web app, l'intero server Web smetterà di funzionare finché non si reimposta esso. Quindi è importante rilevare cicli in fase di validazione.
  2. Se si dispone di più di un paio di formule, aggregare tutte le chiamate al database in un unico luogo, quindi richiedere tutti i dati in una sola volta. Molto più veloce.
  3. Gli utenti entrerà strambo roba in formule. Un parser che fornisce messaggi di errore utili farà risparmiare un sacco di mal di testa in seguito.

Se gli script personalizzati non ottengono più complesse di quelle che si mostra sopra, sarebbe d'accordo con Sylvestre: Crea il tuo parser, fare un albero e fare la logica da soli. È possibile generare un .Net albero di espressione o semplicemente passare attraverso la sintassi albero di se stessi e fare le operazioni all'interno il proprio codice (Antlr di seguito vi aiuterà a generare tale codice).

Poi, si è in controllo completo dei vostri riferimenti, siete sempre all'interno di C #, quindi non è necessario preoccuparsi di gestione della memoria (non più di quanto si farebbe normalmente) ecc IMO Antlr è lo strumento migliore per fare questo in C #. È possibile ottenere esempi dal sito per piccole lingue, come lo scenario.

Ma ... se questo è davvero solo un inizio e alla fine è necessario quasi tutta la potenza di un linguaggio di scripting corretta, si avrebbe bisogno di andare in incorporando un linguaggio di scripting per il vostro sistema. Con i numeri, si avrà un problema con le prestazioni, la gestione della memoria e probabilmente i riferimenti come avrete notato. Ci sono diversi approcci, ma non posso davvero dare una raccomandazione per lo scenario:. Non ho mai fatto in tale scala a

Si potrebbe costruire due classi base UnaryOperator (se, quadrato, radice ...) e BinaryOperator (+ - / *) e costruire un albero dall'espressione. Poi valutare l'albero per ogni elemento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top