質問

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

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

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

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トランザクションを開始し、Forumlasをコンパイルします。各「アイテム」は同じトランザクション +コンパイルされた式を使用します(構成ごとに約20の式があり、各アイテムはそれらすべてを使用します)。

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

助言がありますか?

-Update-これは私が行ったものです、ありがとう!http://www.codeproject.com/articles/53611/embedding-ironpython-in-application

役に立ちましたか?

解決

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

他のヒント

アイアンパイソン スクリプトエンジンをアプリケーションに埋め込むことができます。他にも多くのソリューションがあります。実際、「C#Embedded Scripting」のようなものをグーグルで検索して、たくさんのオプションを見つけることができます。他の人よりも簡単に統合する人もいれば、スクリプトをコーディングする方が他の人よりも簡単なものもあります。

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

私は数年前に同様の問題に直面しました。方程式を可能にするために必要な穏やかなトラフィックを備えたWebアプリがあり、あなたと同様の機能が必要で、速くする必要がありました。私はいくつかのアイデアを経験しました。

最初のソリューションには、計算された列をデータベースに追加することが含まれていました。 App Storeのテーブルは、列のプロパティを保存します(たとえば、金額の列、別の割引などがあります)。ユーザーがProperta * 2のような式に入力した場合、コードは基礎となるテーブルを変更して、新しい計算列を持つことになります。列を追加して削除する限り、乱雑です。ただし、いくつかの利点があります。データベース(SQL Server)は、計算を行うのに非常に高速でした。データベースは、私たちのために多くのエラー検出を処理しました。計算された値は、計算されていない値と同じであると見せかけることができたため、計算値ではない既存のコードを変更する必要はありませんでした。

これは、フォーミュラが別の式を参照する機能が必要になるまでしばらく機能し、SQLサーバーはそれを許可しません。そこで、スクリプトエンジンに切り替えました。 Ironpythonは当時あまり成熟していなかったので、私は別のエンジンを選びました...今どれを覚えていません。とにかく、書くのは簡単でしたが、少し遅かったです。多くのことはありませんが、おそらくクエリごとに数ミリ秒ですが、Webアプリの場合、すべてのリクエストにわたって実際に追加されました。

それは私が式のために自分のパーサーを書くことにしたときでした。つまり、2つの値、GetValue( "割引")などに対応するアイテムのクラスを追加するためのプラストケンクラスがあります。ユーザーが新しい式を入力すると、バリデーターが式を解析すると、それが有効であることを確認します(彼らは存在しない列を参照しましたか?)、そして後で解析するのが簡単な半コンパイルされたフォームにそれを保存します。ユーザーが計算された値を要求すると、パーサーは式を読み取り、それを解析し、データベースから必要なデータを把握し、最終回答を計算します。前もってかなりの量の作業が必要でしたが、うまく機能し、非常に速いです。これが私が学んだことです:

  1. ユーザーが式のサイクルにつながる式を入力し、式の値を計算しようとすると、スタックスペースがなくなります。これをWebアプリで実行している場合、Webサーバー全体がリセットされるまで動作を停止します。したがって、検証段階でサイクルを検出することが重要です。
  2. いくつかのフォーミュラがある場合は、すべてのデータベース呼び出しを1つの場所に集計してから、すべてのデータを一度にリクエストします。はるかに高速。
  3. ユーザーは奇抜なものを式に入力します。有用なエラーメッセージを提供するパーサーは、後で多くの頭痛を節約します。

カスタムスクリプトが上記のスクリプトよりも複雑にならない場合、Sylvestreに同意します。独自のパーサーを作成し、ツリーを作成し、自分でロジックを行います。 aを生成できます .NET Expression Tree または、自分で構文ツリーを通過して、独自のコード内で操作を作成します(以下のANTLRは、そのようなコードを生成するのに役立ちます)。

その後、あなたはあなたの参照を完全に制御しています、あなたは常にC#内にいるので、あなたはメモリ管理(あなたが通常する以上のこと)などを心配する必要はありません。 antlr これをC#で行うための最良のツールです。シナリオのように、小さな言語の例をサイトから取得します。

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top