我正在WCF中构建数据服务,我正在使用反射和开放类型的组合,因为需要动态创建一些数据元素。大多数一切都运行良好,但我无法使用过滤器来处理开放类型值。
我得到的错误是:
<message xml:lang="en-US">An error occurred while processing this request.</message>
<innererror>
<message>The method or operation is not implemented.</message>
<type>System.NotImplementedException</type>
<stacktrace> at lambda_method(Closure , GeographyProvider )
at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
at System.Data.Services.DataService`1.SerializeResponseBody(RequestDescription description, IDataService dataService)
at System.Data.Services.DataService`1.HandleRequest()</stacktrace>
</innererror>
我正在使用表达式访问者来重写LINQ表达式,并且它成功地提取了open类型的值。在这一点上,我不确定我需要实现什么方法或操作。在表达式访问者完成它的工作之后,表达式树看起来像这样:
Alteryx.Web.API.DatasetProvider+<GetDatasets>d__0.Where(element =>
(element.Variant == "AGSSTD_701000")).SelectMany(element =>
ConvertChecked(element.Geographies)).Where(element =>
(element.Key == "County")).SelectMany(element =>
ConvertChecked(element.Geographies)).Where(element =>
(element.Key == "36")).SelectMany(element =>
ConvertChecked(element.Geographies)).Where(it =>
Convert(((Invoke((o, name) => GetOpenValue(o, name), it, "POPCY") >= Convert(100000)) == True)))}
我在GetOpenValue方法中设置了一个断点,它被调用并返回正确的值。关于我需要从哪里开始的任何想法?
根据Vitek的建议,我将转换和比较方法的检查添加到我的表达式访问者,但找不到它们。以下是我的访问者代码:
static readonly MethodInfo GetValueOpenPropertyMethodInfo =
typeof(OpenTypeMethods)
.GetMethod(
"GetValue",
BindingFlags.Static | BindingFlags.Public,
null,
new Type[] { typeof(object), typeof(string) },
null
);
static readonly MethodInfo OpenConvertMethodInfo =
typeof(OpenTypeMethods)
.GetMethod(
"Convert",
BindingFlags.Static | BindingFlags.Public,
null,
new Type[] { typeof(object), typeof(ResourceType) },
null
);
static readonly MethodInfo GreaterThanOrEqualMethodInfo =
typeof(OpenTypeMethods)
.GetMethod(
"GreaterThanOrEqual",
BindingFlags.Static | BindingFlags.Public,
null,
new Type[] { typeof(object), typeof(object) },
null
);
static readonly MethodInfo EqualMethodInfo =
typeof(OpenTypeMethods)
.GetMethod(
"Equal",
BindingFlags.Static | BindingFlags.Public,
null,
new Type[] { typeof(object), typeof(object) },
null
);
static readonly Expression<Func<object, string, object>> GetValueOpenReplacement =
(o, name) => GetOpenValue(o, name);
static object GetOpenValue(object o, string name)
{
return (o as OpenDataProvider).GetValue(name);
}
static readonly Expression<Func<object, object, object>> GetGreaterThanOrEqualReplacement =
(left, right) => GetOpenGreaterThanOrEqual(left, right);
static object GetOpenGreaterThanOrEqual(object left, object right)
{
string s = left.ToString();
return true;
}
static readonly Expression<Func<object, object, object>> GetEqualReplacement =
(left, right) => GetOpenEqual(left, right);
static object GetOpenEqual(object left, object right)
{
string s = left.ToString();
return true;
}
protected override Expression VisitMethodCall(
MethodCallExpression node
)
{
if (node.Method == GetValueOpenPropertyMethodInfo)
{
// Arguments[0] - the resource to get property from
// Arguments[1] - the ResourceProperty to get
// Invoke the replacement expression, passing the
// appropriate parameters.
if (node.Arguments[0].Type.BaseType == typeof(OpenDataProvider))
{
OpenDataProvider.RequestValue(((ConstantExpression)node.Arguments[1]).Value.ToString());
}
return Expression.Invoke(
Expression.Quote(GetValueOpenReplacement),
node.Arguments[0],
node.Arguments[1]
);
}
else if (node.Method == OpenConvertMethodInfo)
{
// Arguments[0] – the resource
// Arguments[1] – the ResourceType
// no need to do anything, so just
// return the argument
return this.Visit(node.Arguments[0]);
}
else if (node.Method == GreaterThanOrEqualMethodInfo)
{
// Invoke the replacement expression, passing the
// appropriate parameters.
return Expression.Invoke(
Expression.Quote(GetGreaterThanOrEqualReplacement),
node.Arguments[0],
node.Arguments[1]
);
}
else if (node.Method == EqualMethodInfo)
{
// Invoke the replacement expression, passing the
// appropriate parameters.
return Expression.Invoke(
Expression.Quote(GetEqualReplacement),
node.Arguments[0],
node.Arguments[1]
);
}
return base.VisitMethodCall(node);
}
我在VisitMethodCall方法的所有if块中都放置了断点,但只调用了GetValueOpenProperty块。
谢谢!
答案 0 :(得分:0)
Vitek在这里提供了答案:http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/bfb62cf5-48cc-4435-ae9a-76e4a13d762a
总而言之,ExpressionVisitor需要覆盖VisitBinary方法中的OpenTypeMethods。
感谢你的帮助,Vitek!