2009-04-03 1 views
12

私はそれに渡されるアクションデリゲートに基づいて「アカウント」オブジェクトを変更する方法があります:アクションデリゲートに(ラムダ式)文字列を解析する簡単な方法はありますか?

AlterAccount("Account1234", a => a.Enabled = false); 

...意図したとおり、この作品

public static void AlterAccount(string AccountID, Action<Account> AccountAction) { 
    Account someAccount = accountRepository.GetAccount(AccountID); 
    AccountAction.Invoke(someAccount); 
    someAccount.Save(); 
} 

...しかし、今どのようなI 「試してみて、やりたいDこのようなメソッドを持っている:

public static void AlterAccount(string AccountID, string AccountActionText) { 
    Account someAccount = accountRepository.GetAccount(AccountID); 
    Action<Account> AccountAction = MagicLibrary.ConvertMagically<Action<Account>>(AccountActionText); 
    AccountAction.Invoke(someAccount); 
    someAccount.Save(); 
} 

それは、その後のように使用することができます。

AlterAccount("Account1234", "a => a.Enabled = false"); 

アカウント「Account1234」を無効にします。

linq dynamic query libraryを見てきましたが、多かれ少なかれ、Funcタイプの代理人のためにやっているようですが、私の表現木などの知識は、どのように達成するために十分なものではありませんが欲しいです。

私は欲しいものを簡単に行う方法がありますか、または表現を正しく学習してコードを読み込む必要がありますか?

(私はこれをしたい理由は、ユーザーが変更を実行するためにラムダ式を指定することができますPowerShellのスクリプトから一括更新アカウントオブジェクトの簡単な方法を可能にすることです。)

+0

ハードな方法はSystem.Reflection.Emit.DynamicMethodを使用し、ILコードを生成することであろう。しかし、この場合は、プロパティ名と値を指定し、リフレクションベースのプロパティセッターを持つ構文を受け入れる方が簡単かもしれません。 – eulerfx

+0

はい、私はそれを考えましたが、AlterAccount( "Account1234"、 "a => a.Enabled =!a.Enabled")を呼び出すことができるような、潜在的に強力なものを除外すると思います。 (なぜそれを具体的にしたいのか分かりませんが、他のより賢明な例があります) – Whisk

+2

私はこれを読んで良い笑いを持っていました: 'MagicLibrary.ConvertMagically' –

答えて

1

という一般的な方法はありませんラムダ式がラムダ式の外で定義されたものを参照することができるため、文字列を完全なコンパイルなしでラムダ式に構文解析することができます。私はあなたが望む特定のケースを扱うライブラリがないことを知っています。 C#ディスカッショングループのthreadにはこれに関する長い議論があります。

あなたが望むものを得る最も簡単な方法は、実行時にメソッドをコンパイルすることです。文字列 "a.Enabled = true; return a;"を取り出す関数を書くことができます。 Accountをパラメータとする関数の途中でそれを固執します。このlibraryを出発点として使用しますが、another threadに記載されている関数を使用することもできます。

+0

ありがとうございました - 評価するときにはうまくいきませんアクションの代理人に "a => a.Enabled = true"のような文字列 - 私は何か間違っているか、それは完全なC#ステートメントではないので動作しませんか?私は明確にするために質問を更新しました。 – Whisk

+0

rossfabricant;彼が言及しているダイナミックなlinqライブラリはまさにこれを行います。もちろん、コンパイルするときに入力情報を提供する必要がありますが、コンパイルはうまくいきます。 – MichaelGG

+0

クエリを作成することはできますが、状態を変更するものはすべてビルドできることはわかりませんでした。 – RossFabricant

3

Dynamic LINQライブラリは軽量な方法でコードをコンパイルできる式を生成するため、最適な選択です。

実際に提供した例はブール値を生成するので、Funcを要求することができ、それを並べ替えることができます。

編集:これはもちろん、式には割り当てが全くないため間違っています。

もう一つの潜在的な方法は、2つのラムダを取ることです。と最初のラムダで参照プロパティを設定するためにリフレクションを使用して次に(A =>真)

(A => a.AccountId):1の値を提供するために、必要なプロパティを見つけるための一つ2番目の結果。 Hackishですが、おそらくC#コンパイラを呼び出すのに比べて軽量です。

このようにすれば、自分でコードを多用する必要はありません。必要なすべてのものがあなたに与えられます。簡単だ

+0

私は思っています... "a => a.Enabled == false"を実行していればうまくいくが、 "a => a.Enabled = false"を実行している - アカウントなので、何も変更しなくてもうまくいくとは思えません。 – Whisk

+0

あなたは正しいです。それはfuncsのために働く:Func exp =()=> test = false;式には使用できません。割り当てを表す方法がないためです。 – MichaelGG

+0

ええ - 私は、動的LINQの動作を、動作とFunc で動作するように変更しようとしていると思います。 – Whisk

0

  • 使用CodeDomあなたが式を作成するために使用します「周囲のクラス」を含むモジュールを生成します。このクラスは、アプリケーションに既知のインターフェイスを実装する必要があります
  • CodeSnippedExpressionを使用して、そのメンバに式を挿入します。
  • 実行時にこのクラスのインスタンスを作成するには、Activatorタイプを使用します。

基本的に、あなたがたCodeDOMと以下のクラスを構築する必要があります:

using System; 
using MyNamespace1; 
using ... 
using MyNamespace[N]; 

namespace MyNamespace.GeneratedTypes 
{ 
    public class ExpressionContainer[M] : IHasAccountAction 
    { 
    public Action<Account> AccountAction { 
     get { 
     return [CodeSnippedExpression must be used here]; 
     } 
    } 
    } 
} 

IHasAccountActionがあると仮定すると:これが行われた場合

public IHasAccountAction { 
    public Action<Account> AccountAction { get; } 
} 

、あなたは表現が文字列からコンパイルされ得ることができます簡単に。式ツリー表現が必要な場合は、生成タイプにAction<Account>の代わりにExpression<Action<Account>>を使用してください。

+0

(ジェネリックオペレーター、あなたのコメントに返信、btw) –

3

あなたはこれを試すことがあります。Dynamic Lambda Expressions Using An Isolated AppDomain

それはのCodeDOMコンパイラを使用してラムダ式をコンパイルします。作成されたインメモリアセンブリを破棄するために、コンパイラは分離されたAppDomainで実行されます。ドメイン境界を介して式を渡すには、それをシリアル化する必要があります。 Alas、Expression<>Serializableではありません。したがって、トリックを使用する必要があります。すべての詳細はポストで説明されています。

私はそのコンポーネントの作成者です。私はあなたからのフィードバックを非常に聞きたい。

1

あなたは少し異なる場合がありSpring.NETのlambda expression evaluation engine

表現を使用することができますが、まだあなたは、発現のための文字列を使用します。

関連する問題