1

関数式ツリーが オブジェクトExpression<Func<TClass, TProperty>>型のグローバル変数に割り当てられ、コードの後半で式を使用して別のメソッドを呼び出す必要があるという状況になりました。グローバル オブジェクト タイプを変更できません。オブジェクトでなければなりません。

オブジェクトを としてキャストしない限り、グローバル オブジェクトで 2 番目のメソッドを呼び出そうとすると、コードはコンパイルされませんExpression<Func<TClass, TProperty>>。問題は、2 番目のメソッドが呼び出された時点でTPropertyが何であるかわからないことです。

ポイントを説明するために簡単なデモ アプリを作成しました (VS2010 で記述された c# コンソール アプリ) - 実際のアプリケーションはこのようには見えません。

using System;
using System.Linq.Expressions;

namespace FuncExpressionTree
{
    public class ViewModel
    {
        public string StringProperty { get; set; }
        public int IntProperty { get; set; }
    }

    public class Helper<T>
        where T : ViewModel
    {
        private object _global;

        public void Execute()
        {
            AssignToGlobal((T vm) => vm.StringProperty);

            ProcessGlobal();

            AssignToGlobal((T vm) => vm.IntProperty);

            ProcessGlobal();
        }

        public void AssignToGlobal<TClass, TProperty>(Expression<Func<TClass, TProperty>> expression)
        {
            _global = expression;
        }

        public void ProcessGlobal()
        {
            // invalid cast exception thrown when IntProperty is assigned to _global
            AssignToGlobal((Expression<Func<T, string>>)_global);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            (new Helper<ViewModel>()).Execute();
        }
    }
}

メソッドに注目するとExecute()

  1. 最初のグローバルには、文字列プロパティの式が割り当てられます。
  2. ProcessGlobal にキャストしているため、 ProcessGlobal が実行されて機能しExpression<Func<T, string>>ます。
  3. 次のグローバルには、int プロパティの式が割り当てられます。
  4. ProcessGlobal は再び実行されますが、この時点で無効なキャスト例外がスローされます。代わりにキャストに変更すると機能しExpression<Func<T, int>>ますが、文字列プロパティは機能しません。またExpression<Func<T, object>>、無効なキャスト例外をスローします。

私は何かが欠けているように感じます.2番目のメソッドを動的に呼び出すために名前空間で何かを行うことができるはずですSystem.Linq.Expressions(たとえば、上記の例のProcessGlobal内のAssignToGlobal)。

では、どうすればこれを一般的な方法で機能させることができますか?

4

1 に答える 1

1
    public void ProcessGlobal()
    {
        var globalType = _global.GetType(); // globalType = Expression<Func<TClass, TProperty>>
        var functionType = globalType.GetGenericArguments()[0]; // functionType = Func<TClass, TProperty>
        var functionGenericArguments = functionType.GetGenericArguments(); // v = [TClass, TProperty]
        var method = this.GetType().GetMethod("AssignToGlobal").MakeGenericMethod(functionGenericArguments); //functionGenericArguments = AssignToGlobal<TClass, TProperty>
        method.Invoke(this, new[] { this._global }); // Call AssignToGlobal<TClass, TProperty>)(this._global);
    }
于 2012-07-17T00:39:37.260 に答える