ユーザーによるクエリ入力を表す式ツリーを作成する必要があるという、ちょっとした課題があります。ユーザー入力の考えられるすべてのケースを作成する時間がないため、式ツリーがこれを解決するのに役立つと考えました。
ほとんどの場合、それはあります。しかし、私は少し困惑しています。以下のコードでは、動的に作成された式で List.Find を実行しようとしています。式は、要するに次のとおりです。
list.Find(m => m.ListOfStrings.Exists(s => s == "cookie"));
m はどこですか
class MyClass
{
public List<string> ListOfStrings { get; set; }
}
作成するまでになりました
s => s == "cookie"
式で、問題ありません。Exists の methodinfo も宣言しました
var existsMethod = typeof(MyClass)
.GetProperty("ListOfStrings")
.PropertyType
.GetMethod("Exists");
私が抱えている唯一の問題は、ラムダをパラメーターとして使用して上記のメソッドを呼び出す式を作成することです
var findLambda = Expression.Lambda(
Expression.Call(
Expression.Property(
Expression.Parameter(typeof(MyClass), "m"),
typeof(MyClass).GetProperty("ListOfStrings")),
existsMethod,
existsLambda),
Expression.Parameter(
typeof (MyClass),
"m"));
それは理解できる例外を与えます
Expression of type 'System.Func`2[System.String,System.Boolean]' cannot be used for parameter of type 'System.Predicate`1[System.String]' of method 'Boolean Exists(System.Predicate`1[System.String])'
どうすればこれを克服できますか?
完全なコード:
private class MyClass
{
public List<string> ListOfStrings { get; set; }
}
public void SomeMethod()
{
var myObject = new MyClass();
myObject.ListOfStrings = new List<string>();
myObject.ListOfStrings.Add("cookie");
myObject.ListOfStrings.Add("biscuit");
List<MyClass> list = new List<MyClass>();
list.Add(myObject);
var existsLambda = Expression.Lambda(
Expression.Equal(
Expression.Parameter(typeof(string), "s"),
Expression.Constant("cookie")),
Expression.Parameter(typeof(string), "s"));
var existsMethod = typeof(MyClass).GetProperty("ListOfStrings").PropertyType.GetMethod("Exists");
var findLambda = Expression.Lambda(
Expression.Call(
Expression.Property(
Expression.Parameter(typeof(MyClass), "m"),
typeof(MyClass).GetProperty("ListOfStrings")),
existsMethod,
existsLambda),
Expression.Parameter(
typeof (MyClass),
"m"));
list.Find((Predicate<MyClass>)findLambda.Compile());
}