Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Objects / ELinq / BindingContext.cs
1 //---------------------------------------------------------------------
2 // <copyright file="BindingContext.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner  [....]
7 //---------------------------------------------------------------------
8
9 using CqtExpression = System.Data.Common.CommandTrees.DbExpression;
10 using LinqExpression = System.Linq.Expressions.Expression;
11 using System.Linq.Expressions;
12 using System.Collections.ObjectModel;
13 using System.Linq;
14 using System.Collections.Generic;
15 using System.Data.Common.CommandTrees;
16 using System.Data.Metadata.Edm;
17 using System.Reflection;
18 using System.Data.Common.EntitySql;
19 using System.Diagnostics;
20 using System.Data.Common;
21 using System.Globalization;
22 namespace System.Data.Objects.ELinq
23 {
24     /// <summary>
25     /// Class containing binding information for an expression converter (associating CQT bindings
26     /// with LINQ lambda parameter or LINQ sub-expressions)
27     /// </summary>
28     /// <remarks>
29     /// Usage pattern:
30     /// <code>
31     /// BindingContext context = ...;
32     /// 
33     /// // translate a "Where" lamba expression input.Where(i => i.X > 2);
34     /// LambdaExpression whereLambda = ...;
35     /// CqtExpression inputCqt = Translate(whereLambda.Arguments[1]);
36     /// CqtExpression inputBinding = CreateExpressionBinding(inputCqt).Var;
37     /// 
38     /// // push the scope defined by the parameter 
39     /// context.PushBindingScope(new KeyValuePair{ParameterExpression, CqtExpression}(whereLambda.Parameters[0], inputBinding));
40     /// 
41     /// // translate the expression in this context
42     /// CqtExpression result = Translate(whereLambda.Expression);
43     /// 
44     /// // pop the scope
45     /// context.PopBindingScope();
46     /// </code>
47     /// </remarks>
48     internal sealed class BindingContext
49     {
50         private readonly Stack<Binding> _scopes;
51
52         /// <summary>
53         /// Initialize a new binding context
54         /// </summary>
55         internal BindingContext()
56         {
57             _scopes = new Stack<Binding>();
58         }
59
60         /// <summary>
61         /// Set up a new binding scope where parameter expressions map to their paired CQT expressions.
62         /// </summary>
63         /// <param name="binding">DbExpression/LinqExpression binding</param>
64         internal void PushBindingScope(Binding binding)
65         {
66             _scopes.Push(binding);
67         }
68
69         /// <summary>
70         /// Removes a scope when leaving a particular sub-expression.
71         /// </summary>
72         /// <returns>Scope.</returns>
73         internal void PopBindingScope()
74         {
75             _scopes.Pop();
76         }
77
78         internal bool TryGetBoundExpression(Expression linqExpression, out CqtExpression cqtExpression)
79         {
80             cqtExpression = _scopes
81                 .Where(binding => binding.LinqExpression == linqExpression)
82                 .Select(binding => binding.CqtExpression)
83                 .FirstOrDefault();
84             return cqtExpression != null;
85         }
86     }
87
88     /// <summary>
89     /// Class describing a LINQ parameter and its bound expression. For instance, in
90     /// 
91     /// products.Select(p => p.ID)
92     /// 
93     /// the 'products' query is the bound expression, and 'p' is the parameter.
94     /// </summary>
95     internal sealed class Binding
96     {
97         internal Binding(Expression linqExpression, CqtExpression cqtExpression)
98         {
99             EntityUtil.CheckArgumentNull(linqExpression, "linqExpression");
100             EntityUtil.CheckArgumentNull(cqtExpression, "cqtExpression");
101             LinqExpression = linqExpression;
102             CqtExpression = cqtExpression;
103         }
104
105         internal readonly Expression LinqExpression;
106         internal readonly CqtExpression CqtExpression;
107     }
108 }