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

Provide a way to extend the customize the expression processing pipeline in the re-linq front-end

    XMLWordPrintable

    Details

    • Type: New Feature
    • Status: Closed (View Workflow)
    • Priority: Normal
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 1.13.92
    • Component/s: Data.Linq
    • Labels:
      None

      Description

      A new mechanism has been added that allows re-linq-based providers to customize the expression processing pipeline in the re-linq front-end. This feature can be used to implement complex expression transformations (eg., expression visitor runs), to remove the partial evaluation feature included in the expression pipeline by default, or to add an additional partial evaluation step after the transformation step has run.

      Note that for simple expression transformations, the predefined expression transformation support should be used as it is more efficient than an additional expression tree run.

      The following classes and interfaces are involved:

      • Interface IExpressionTreeProcessingStep: Implement this interface to define a custom processing step. When creating a QueryParser, include this step in the pipeline. The Process method will then be called for the root node of the expression tree when a query is parsed.
      • Class PartialEvaluationStep: This is a predefined step that evaluates parts of an expression tree in-memory. An instance of this step is automatically included in the pipeline created by ExpressionTreeParser.CreateDefaultProcessingSteps.
      • Class ExpressionTransformationStep: This is a predefined step that executes a sequence of expression transformations when a query is parsed. An instance of this step is automatically included in the pipeline created by ExpressionTreeParser.CreateDefaultProcessingSteps.

      To customize the processing steps executed by a LINQ provider, use a QueryParser that includes the steps to be processed. You can use the ExpressionTreeParser.CreateDefaultProcessingSteps method to get the steps included by default.

      The following example creates a highly customizable instance of a class MyQueryable<T>, which has a custom processing step registered after all default steps have executed. It is of course possible to use a dependency injection container rather than manually composing the queryProvider.

      public static MyQueryable<T> CreateQuery<T>()
      {
        // include default nodes
        var nodeTypeRegistry = MethodCallExpressionNodeTypeRegistry.CreateDefault();
      
        // include default transformations, and add new ones
        var transformerRegistry = ExpressionTransformerRegistry.CreateDefault();
      
        // extend default pipeline with a custom step
        var defaultProcessingSteps = ExpressionTreeParser.CreateDefaultProcessingSteps (transformerRegistry);
        var processingSteps = new List<IExpressionTreeProcessingStep> (defaultProcessingSteps) { new CustomStep () }.ToArray(); 
      
        // create an ordinary QueryParser that uses the objects defined so far
        var expressionTreeParser = new ExpressionTreeParser (nodeTypeRegistry, processingSteps);
        var queryParser = new QueryParser (expressionTreeParser);
      
        // the query executor represents the LINQ provider's back-end
        var queryExecutor = new MyQueryExecutor();
      
        // the query provider plumbs queryParser and queryExecutor together
        var queryProvider = new DefaultQueryProvider (queryParser, queryExecutor);
      
        // the queryable is the entry point in the query - and its execution
        return new MyQueryable<T> (queryProvider);
      }
      

      (Note that QueryParser and DefaultQueryProvider do not change state between different queries, so they can be stored and reused with "singleton" semantics.)

        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: