私の目的には問題なく動作する基本的な (素朴な?) LINQ プロバイダーを実装しましたが、対処したい癖がいくつかありますが、その方法がわかりません。例えば:
// performing projection with Linq-to-Objects, since Linq-to-Sage won't handle this:
var vendorCodes = context.Vendors.ToList().Select(e => e.Key);
私のIQueryProvider
実装には、次のCreateQuery<TResult>
ような実装がありました。
public IQueryable<TResult> CreateQuery<TResult>(Expression expression)
{
return (IQueryable<TResult>)Activator
.CreateInstance(typeof(ViewSet<>)
.MakeGenericType(elementType), _view, this, expression, _context);
}
明らかに、これはExpression
が aMethodCallExpression
でありTResult
である場合にチョークします。string
public IQueryable<TResult> CreateQuery<TResult>(Expression expression)
{
var elementType = TypeSystem.GetElementType(expression.Type);
if (elementType == typeof(EntityBase))
{
Debug.Assert(elementType == typeof(TResult));
return (IQueryable<TResult>)Activator.CreateInstance(typeof(ViewSet<>).MakeGenericType(elementType), _view, this, expression, _context);
}
var methodCallExpression = expression as MethodCallExpression;
if(methodCallExpression != null && methodCallExpression.Method.Name == "Select")
{
return (IQueryable<TResult>)Execute(methodCallExpression);
}
throw new NotSupportedException(string.Format("Expression '{0}' is not supported by this provider.", expression));
}
そのため、実行するvar vendorCodes = context.Vendors.Select(e => e.Key);
とprivate static object Execute<T>(Expression,ViewSet<T>)
オーバーロードが発生し、最も内側のフィルター式のメソッド名がオンになり、基になる API で実際の呼び出しが行われます。
さて、この場合、Select
メソッド呼び出し式を渡しているので、フィルター式はnull
あり、switch
ブロックはスキップされます-これは問題ありません-私が行き詰まっている場所は次のとおりです。
var method = expression as MethodCallExpression;
if (method != null && method.Method.Name == "Select")
{
// handle projections
var returnType = method.Type.GenericTypeArguments[0];
var expType = typeof (Func<,>).MakeGenericType(typeof (T), returnType);
var body = method.Arguments[1] as Expression<Func<T,object>>;
if (body != null)
{
// body is null here because it should be as Expression<Func<T,expType>>
var compiled = body.Compile();
return viewSet.Select(string.Empty).AsEnumerable().Select(compiled);
}
}
MethodCallExpression
LINQ-to-Objects のSelect
メソッドに渡すことができるようにするには、何をする必要がありますか? 私はこれに正しく近づいていますか?