理解できないラムダ式ツリーの問題があります。動的な linq Select ステートメントを作成しようとしています。
ここに作成された動的リポジトリがあります:
private static dynamic GetRepository(Type type)
{
dynamic repository = typeof(IFactory).GetMethod("Create").MakeGenericMethod(typeof(IRepository<>).MakeGenericType(type)).Invoke(ObjectFactory.Instance, new object[] { });
return repository;
}
これで、コンパイル時に x と SomeProperty がわからないだけで、これを呼び出す必要があります。私は SomeProperty 名を持つ PropertyInfo propertyInfo と x タイプの Type objectType を持っています。次の例外を除いて、目標 1 で失敗します。
GetMethod(文字列名)でのSystem.Reflection.AmbiguousMatchException
コード:
private SomeObject CreateSomeObject (PropertyInfo propertyInfo, Type objectType)
{
var param = Expression.Parameter(objectType, "x");
MemberExpression expression = Expression.PropertyOrField(param, propertyInfo.Name);
//Goal 1: var selectExpression = Expression.Lambda<Func<objectType, object>>(expression, param);
var selectExpression = typeof(Expression).GetMethod("Lambda").MakeGenericMethod(typeof(Func<,>)
.MakeGenericType(objectType, typeof(object)))
.Invoke((object)null, new object[] { expression, param });
// Goal 2: List<object> list = GetRepository(objectType).FindAllQuery().Select(x => x.SomeProperty).ToList();
List<object> list = GetRepository(objectType).FindAll().Select(selectExpression);
}
これを解決するには?
更新 1:
Lambda メソッドの選択方法、「param」パラメータのパック方法を変更し、「expression」にオブジェクト コンバーターを追加しました。
private SomeObject CreateSomeObject (PropertyInfo propertyInfo, Type objectType)
{
var param = Expression.Parameter(objectType, "x");
Expression expression = Expression.Convert(Expression.PropertyOrField(param, propertyInfo.Name), typeof(object));
//Goal 1: var selectExpression = Expression.Lambda<Func<objectType, object>>(expression, param);
var selectExpression = typeof(Expression).GetMethods().First(m => m.Name == "Lambda" && m.IsGenericMethod)
.MakeGenericMethod(typeof(Func<,>)
.MakeGenericType(objectType, typeof(object)))
.Invoke((object)null, new object[] { expression, new [] { param }});
// Goal 2: List<object> list = GetRepository(objectType).FindAllQuery().Select(x => x.SomeProperty).ToList();
List<object> list = GetRepository(objectType).FindAll().Select(selectExpression);
}
ただし、目標 2 (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) でこの例外が発生することを知っています。
「System.Collections.Generic.List」には「Select」の定義が含まれていません
System.Linq で定義されており、拡張メソッドであるため、これは部分的に正しいです。これを機能させるにはどうすればよいですか?