14

渡されたアクション デリゲートに基づいて「アカウント」オブジェクトを変更するメソッドがあります。

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

これは意図したとおりに機能します...

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

...しかし、今私が試してみたいのは、次のような方法です:

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 スクリプトからアカウント オブジェクトを簡単に一括更新できるようにするためです。)

4

4 に答える 4

4

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

あなたが提供した例は実際にブール値を生成します-したがって、 Func を要求できるはずであり、それが整理される可能性があります。

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

したがって、もう 1 つの考えられる方法は、2 つのラムダを取ることです。1 つは必要なプロパティを見つけるためのもので、もう 1 つは値を提供するためのものです。

(a => a.AccountId)、(a => true)

次に、リフレクションを使用して、最初のラムダで参照されるプロパティを 2 番目のラムダの結果で設定します。ハックですが、C# コンパイラを呼び出すのに比べればまだ軽量です。

この方法では、多くの codegen を自分で行う必要はありません。得られる式には、必要なほとんどすべてが含まれています。

于 2009-04-03T17:23:32.283 に答える
3

これを試すことができます:分離された AppDomain を使用した動的ラムダ式

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

ところで、私はそのコンポーネントの作成者です。そこからのフィードバックをぜひお聞かせください。

于 2009-09-05T06:39:17.667 に答える
1

ラムダ式はラムダ式の外部で定義されているものを参照できるため、完全なコンパイルを行わずに文字列をラムダ式に解析する一般的な方法はありません。あなたが望む特定のケースを処理するライブラリはありません。これについては、C# ディスカッション グループのスレッドで長い議論があります。

必要なものを取得する最も簡単な方法は、実行時にメソッドをコンパイルすることです。文字列「a.Enabled = true; return a;」を受け取る関数を作成できます。Account をパラメーターとして受け取る関数の途中にそれを貼り付けます。このライブラリを出発点として使用しますが、別のスレッドで言及されている関数を使用することもできます。

于 2009-04-03T17:04:35.137 に答える
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; }
}

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

于 2009-07-05T12:00:38.070 に答える