Uploaded image for project: 're-motion'
  1. re-motion
  2. RM-3343

Add a filtering mechanism to expression node types registered by names

    XMLWordPrintable

    Details

      Description

      The MethodCallExpressionNodeTypeRegistry has been replaced by an interface (INodeTypeProvider) with several implementations. One of them, the MethodNameBasedNodeTypeRegistry, provides support for registering expression node parsers by name (rather than MethodInfo). Since the method name is usually not enough to distinguish query operators, a registration also contains a filter predicate that determines whether a node parser is suitable for parsing a specific query operator method.

      Consider the following example:

      public class MyContainsExpressionNode : ResultOperatorExpressionNodeBase
      {
        public static readonly MethodInfo[] SupportedMethods = new[]
            {
              GetSupportedMethod (() => Queryable.Contains<object> (null, null)),
              GetSupportedMethod (() => Enumerable.Contains<object> (null, null)),
            };
      
        public static readonly NameBasedRegistrationInfo[] SupportedMethodNames = new[]
            {
              new NameBasedRegistrationInfo (
                  "Contains",
                  mi => mi.DeclaringType != typeof (string) && typeof (IEnumerable).IsAssignableFrom (mi.DeclaringType)
                      && (mi.IsStatic && mi.GetParameters().Length == 2 || !mi.IsStatic && mi.GetParameters().Length == 1))
            };
      
        // ...
      }
      

      This code defines that the given MyContainsExpressionNode is registered for the Contains query operators defined by the Queryable and Enumerable classes, and, in addition, for all methods called "Contains" (with the right argument count) declared by classes implementing IEnumerable. Only "string" is exempt, since string.Contains is usually not desired to be seen as a query operator.

      (This code is how the ContainsExpressionNode class is currently defined in re-linq.)

      To use such a custom expression node parser, create a MethodNameBasedNodeTypeRegistry when creating the QueryParser in your LINQ provider.

      private static IQueryParser CreateQueryParser ()
      {
        var customNodeTypeRegistry = new MethodInfoBasedNodeTypeRegistry();
        // Register custom node parsers here:
        // customNodeTypeRegistry.Register (MyExpressionNode.SupportedMethods, typeof (MyExpressionNode));
        // Alternatively, use the CreateFromTypes factory method.
        // Use MethodNameBasedNodeTypeRegistry to register parsers by query operator name instead of MethodInfo.
      
        var nodeTypeProvider = ExpressionTreeParser.CreateDefaultNodeTypeProvider ();
        nodeTypeProvider.InnerProviders.Add (customNodeTypeRegistry);
      
        var transformerRegistry = ExpressionTransformerRegistry.CreateDefault ();
        // Register custom expression transformers here:
        // transformerRegistry.Register (new MyExpressionTransformer());
      
        var processor = ExpressionTreeParser.CreateDefaultProcessor (transformerRegistry);
        // Add custom processors here:
        // processor.InnerProcessors.Add (new MyExpressionTreeProcessor());
      
        var expressionTreeParser = new ExpressionTreeParser (nodeTypeProvider, processor);
        var queryParser = new QueryParser (expressionTreeParser);
      
        return queryParser;
      }
      

        Attachments

          Issue Links

          There are no Sub-Tasks for this issue.

            Activity

              People

              • Assignee:
                fabian.schmied Fabian Schmied
                Reporter:
                fabian.schmied Fabian Schmied
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Time Tracking

                  Estimated:
                  Original Estimate - 3 hours Original Estimate - 3 hours
                  3h
                  Remaining:
                  Remaining Estimate - 0 minutes
                  0m
                  Logged:
                  Time Spent - 4 hours
                  4h