7

expando オブジェクトを使用しており、計算されたプロパティを定義しようとしています。

次のようなことを行うことで、単純なプロパティを定義できることを知っています。

dynamic myExpando = new ExpandoObject();
myExpando.TheAnswerToLifeTheUniverseAndEverything= 42;

同様に、メソッドを定義することもできます。

myExpando.GetTheQuestion = ((Func<string>)(() =>
        {
            return "How many road must a man walk down before we can call him a man?";
        }));  

標準オブジェクトを操作する場合、計算プロパティを定義できます。つまり、カスタム メソッド/計算の結果を返すプロパティを定義できます。例は必要ありません。

expando で同様のことを行う必要があります。実際に「Func」を呼び出すプロパティ (または他の形式のデリゲート、カスタム メソッドを呼び出してカスタムの戻り値の型を取得できるとすぐにすべてが実行されます) が必要です。したがって、基本的には、2 番目の例のようにメソッドを呼び出す必要がありますが、プロパティのように機能させる必要があります。

基本的に、カスタム デリゲートをプロパティ本体として定義する機能を維持しながら、myExpando.GetTheQuestion()の代わりにmyExpando.GetTheQuestionで呼び出すことができる必要があります。

これを行う方法はありますか?式ツリーを使用すればこれができると思いますが、少し迷っていることは認めます。これを達成する方法について誰かがガイダンスを提供できますか??


編集

さらに調査を行いました..私が知らない非常に特定のクラス/インターフェース/シンタックスがない限り、上記は不可能だと思い始めています。私が得た情報によると、ExpandoObject クラスは、TryGetMember、TrySetMember などのバックグラウンド プラミングを行ういくつかのメソッドを定義することによって機能します。これで、動的 objetc で「プロパティにアクセス」するときに、TryGetMember が呼び出されるメンバーになります。そのメンバーは、一種の内部辞書から値を返します (はい、私は知っています...これは少し単純化されていますが、アイデアを与える必要があります)...返される値の型に関するテストはありません。これは、私の例では、myExpando.GetTheQuestionが元の Func を返すことを意味します。

TryGetMember は値を返すだけなので、プロパティ コードを "実行" する方法はないようです。それを達成するには、実際にはメソッドの結果である何らかの式/ラムダ/機能/アクション サロゲートが必要です。これは不可能に思えます(何かを見逃さない限り、あまり意味がありません-基本的に、「デリゲート」に設定された値があり、デリゲートの戻り値として取得されます???)。私は正しいですか、これですか、それとも何か不足していますか?

4

1 に答える 1

2

DynamicObject継承およびオーバーライドして、独自の ExpandoObject を作成する必要があります

public override bool TryGetMember(GetMemberBinder binder, out object result)public override bool TrySetMember(SetMemberBinder binder, object value)

TrySetMember値をプライベートDictionary<string,object>アンダーに保存し、そのディクショナリから値を取得するために実装します。これにより、基本的な ExpandoObject が得られbinder.Nameます。TryGetMember次に、必要な機能を提供するためにTryGetMember、オブジェクトをプルした後にチェックインを追加して、それを確認し、is Delagateリフレクションを使用して引数を取らないかどうかを確認します。両方が true の場合は、 にキャストしてdynamicarg 呼び出し括弧を追加せずに に割り当てますresult

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
      if (_dictionary.TryGetValue(binder.Name, out result)){
           if(result is Delegate && /* some reflection check on args*/){
                result = ((dynamic)result)();
           }
      }
}

私はオープン ソース フレームワーク ImpromptuInterface (nuget 内) を持っています。これは、特にgui バインディング サポートなどのより微妙な機能が必要な場合に、代わりに開始できる非密閉型を持っています。 また、便利なdlr 配管機能も備えています。ImpromptuDictionaryExpandoObjectExpandoObject

于 2013-02-11T17:05:06.410 に答える