Не удается получить фильтр $ для работы с открытыми типами в службе данных WCF - PullRequest
0 голосов
/ 17 мая 2011

Я строю службу данных в 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 )&#xD;
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()&#xD;
   at System.Data.Services.DataService`1.SerializeResponseBody(RequestDescription description, IDataService dataService)&#xD;
   at System.Data.Services.DataService`1.HandleRequest()</stacktrace>
  </innererror>

Я использую посетитель выражений дляпереписать выражения LINQ, и оно успешно извлекает значение для открытого типа.На данный момент я не уверен, какой метод или операция мне нужно реализовать.Дерево выражений выглядит следующим образом после того, как посетитель выражения выполнил свою работу:

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, я добавил проверки для Convert и методы сравнения для моего посетителя выражения, но они не найдены.Вот как выглядит мой код посетителя:

    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);
    }

Я установил контрольные точки во всех блоках if в методе VisitMethodCall, но когда-либо вызывался только блок GetValueOpenProperty.

Спасибо!

1 Ответ

0 голосов
/ 23 мая 2011

Vitek любезно предоставил ответ на этот вопрос здесь: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/bfb62cf5-48cc-4435-ae9a-76e4a13d762a

Чтобы подвести итог, ExpressionVisitor должен переопределить методы OpenTypeMethods в методе VisitBinary.

Спасибо за помощь, Vitek!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...