2

ユーザーがデータに基づいて値を計算する式を定義できるようにする必要があります。例えば

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

/ * + - 操作を許可し、ローカル変数を割り当てて IF ステートメントを実行する必要があります。

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

私は次の構造を持っているので、シナリオは複雑です..

  1. 顧客(数百)
  2. 構成 (顧客ごとに約 10)
  3. 項目 (顧客構成ごとに約 10,000)

そこで、3 レベルのループを実行します。各「構成」レベルで、DB トランザクションを開始してフォーラムをコンパイルします。各「アイテム」は同じトランザクション + コンパイルされた数式を使用します (構成ごとに約 20 の数式があり、各アイテムはそれらすべてを使用します)。

メモリ使用量が継続的に増加するため、コンパイラ サービスだけを使用することはできないため、これは事態をさらに複雑にします。渡す必要のある参照の一部をマーシャリングできないため、各「構成」ループ レベルごとに新しい AppDomain を使用できません。

助言がありますか?

--更新--これは私が行ったものです、ありがとう! http://www.codeproject.com/Articles/53611/Embedding-IronPython-in-aC-Application

4

5 に答える 5

2

Iron Pythonスクリプト エンジンをアプリケーションに埋め込むことができます。他にも多くの解決策があります。実際、「C# 埋め込みスクリプト」などをググると、たくさんのオプションを見つけることができます。他のものよりも簡単に統合できるものもあれば、他のものより簡単にスクリプトをコーディングできるものもあります。

もちろん、常に VBA があります。しかし、それは実に醜いです。

于 2010-05-18T13:16:16.443 に答える
1

カスタムスクリプトが上に示したものよりも複雑にならない場合は、Sylvestreに同意します。独自のパーサーを作成し、ツリーを作成して、ロジックを自分で実行します。.Net式ツリーを生成するか、構文ツリーを自分で調べて、独自のコード内で操作を行うことができます(以下のAntlrは、そのようなコードの生成に役立ちます)。

そうすれば、参照を完全に制御でき、常にC#内にいるので、メモリ管理(通常よりも多く)などについて心配する必要はありません。IMOAntlrは、C#でこれを行うための最良のツールです。シナリオのように、サイトから小さな言語の例を入手します。

しかし...これが本当に始まりに過ぎず、最後に適切なスクリプト言語のほぼ完全な能力が必要な場合は、システムにスクリプト言語を埋め込む必要があります。あなたの数では、あなたが指摘したように、パフォーマンス、メモリ管理、そしておそらく参照に問題があります。いくつかのアプローチがありますが、私はあなたのシナリオに対して1つの推奨事項を実際に与えることはできません。私はそのような規模でそれを行ったことがありません。

于 2010-05-18T15:01:06.947 に答える
1

ロジックを文字列などに記述し、コンパイルして実行し、必要な計算を返すようにするだけで、実行時に単純なクラスを作成できます。この記事では、ランタイムからコンパイラにアクセスする方法を示します: http://www.codeproject.com/KB/cs/codecompilation.aspx

于 2010-05-18T13:19:01.733 に答える
1

私は数年前に同様の問題に直面しました。方程式を許可するために必要な中程度のトラフィックを持つ Web アプリがあり、それはあなたと同様の機能を必要とし、高速でなければなりませんでした。私はいくつかのアイデアを経験しました。

最初の解決策は、データベースに計算列を追加することでした。アプリのテーブルには、プロパティが列に格納されます (たとえば、Amount due の列、別の割引などの列があります)。ユーザーが PropertyA * 2 のような数式を入力した場合、コードは基になるテーブルを変更して、新しい計算列を作成します。列の追加と削除に関しては面倒です。ただし、いくつかの利点があります。データベース (SQL Server) の計算は非常に高速でした。データベースは多くのエラー検出を処理してくれました。また、計算された値が計算されていない値と同じであると見なすことができました。つまり、計算されていない値を処理する既存のコードを変更する必要はありませんでした。

数式が別の数式を参照する機能が必要になるまで、これはしばらくの間うまくいきましたが、SQL Server はそれを許可しませんでした。そこで、スクリプト エンジンに切り替えました。その当時、IronPython はあまり成熟していなかったので、別のエンジンを選びました...今はどれがどれだったか思い出せません。とにかく書きやすかったですが、少し遅かったです。多くはなく、クエリごとに数ミリ秒かもしれませんが、Web アプリの場合、すべてのリクエストで時間が実際に加算されます。

そこで、数式用の独自のパーサーを作成することにしました。つまり、2 つの値を追加する PlusToken クラス、GetValue("Discount") に対応する ItemToken クラスなどがあります。ユーザーが新しい数式を入力すると、バリデーターが数式を解析し、有効であることを確認します (次のようなものです)。存在しない列を参照していませんか?)、後で解析しやすいセミコンパイル形式で保存します。ユーザーが計算値を要求すると、パーサーが式を読み取って解析し、データベースから必要なデータを特定して、最終的な答えを計算します。前もってかなりの作業が必要でしたが、うまく機能し、非常に高速です。これが私が学んだことです:

  1. ユーザーが数式の循環につながる数式を入力し、数式の値を計算しようとすると、スタック領域が不足します。これを Web アプリで実行している場合、リセットするまで Web サーバー全体が機能しなくなります。したがって、検証段階でサイクルを検出することが重要です。
  2. 数式が 2 つ以上ある場合は、すべてのデータベース呼び出しを 1 か所に集約してから、すべてのデータを一度に要求します。はるかに高速。
  3. ユーザーは数式に奇妙なものを入力します。有用なエラー メッセージを提供するパーサーは、後で頭を悩ませる問題を大幅に軽減します。
于 2010-05-18T14:52:44.310 に答える
0

2 つの基本クラス UnaryOperator (if、square、root...) と BinaryOperator (+ - / *) を構築し、式からツリーを構築できます。次に、各アイテムのツリーを評価します。

于 2010-05-18T14:14:22.073 に答える