Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / ClosureBinding.cs / 2 / ClosureBinding.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
//---------------------------------------------------------------------
using System.Collections;
using LinqExpression = System.Linq.Expressions.Expression;
using CqtExpression = System.Data.Common.CommandTrees.DbExpression;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Data.Common.Utils;
using System.Data.Common.CommandTrees;
using System.Globalization;
using System.Data.Metadata.Edm;
using System.Reflection;
using System.Linq;
using System.Threading;
namespace System.Data.Objects.ELinq
{
///
/// Binding between an object parameter or sub-query and LINQ expression that needs to be
/// re-evaluated before executing a query because it is part of the closure.
///
/// Invariants: the binding defines either the Parameter or the Query property, not both.
///
internal abstract class ClosureBinding
{
#region Constructors
private ClosureBinding(LinqExpression sourceExpression)
{
_sourceExpression = sourceExpression;
}
#endregion
#region Fields
private readonly LinqExpression _sourceExpression;
private static readonly string s_parameterPrefix = "p__linq__";
private static long s_parameterNumber;
#endregion
#region Properties
///
/// Gets the query produced by this closure expression. Returns null if no
/// query is produced.
///
internal abstract ObjectQuery Query { get; }
///
/// Gets the expression produced by this closure expression. Returns null if no
/// expression is produced.
///
internal abstract LinqExpression Expression { get; }
///
/// Gets the parameter storing the primitive value produced by this closure expression.
/// Returns null if no primitive value is produced.
///
internal abstract ObjectParameter Parameter { get; }
#endregion
#region Methods
///
/// Evaluates the binding and populates the object parameter value.
///
/// true if the entire expression should be re-evaluated (if a sub-expression has changed);
/// false otherwise
internal abstract bool EvaluateBinding();
internal abstract ClosureBinding CopyToContext(ExpressionConverter context);
internal static bool TryGetTypeUsageForObjectParameter(ObjectParameter parameter, ClrPerspective perspective, out TypeUsage typeUsage)
{
// since ObjectParameters do not allow users to especify 'facets', make
// sure that the parameter typeusage is not populated with the provider
// dafault facet values
if (perspective.TryGetTypeByName(parameter.MappableType.FullName,
false, // bIgnoreCase
out typeUsage) &&
TypeSemantics.IsPrimitiveType(typeUsage))
{
return true;
}
typeUsage = null;
return false;
}
///
/// requires: expression must not be null
/// Attempt to treat the given expression as a supported parameter reference in a closure.
/// Succeeds if the pattern of the expression is precisely Member(Constant), and the member
/// is of primitive type.
///
/// Expression to check.
/// Perspective to use to resolve expression type.
/// Determines whether Lambda sub-expressions are permitted in this context.
/// Closure binding corresponding to the given expression.
/// Type usage for the binding.
/// true if the given expression can be bound
internal static bool TryCreateClosureBinding(LinqExpression expression,
ClrPerspective perspective, bool allowLambda, HashSet closureCandidates, out ClosureBinding binding, out TypeUsage typeUsage)
{
Debug.Assert(null != expression);
if (ExpressionEvaluator.IsExpressionNodeAClosure(expression) &&
closureCandidates.Contains(expression)) // all nodes below it must qualify also
{
ObjectParameter parameter = new ObjectParameter(GenerateParameterName(),
expression.Type);
if(TryGetTypeUsageForObjectParameter(parameter, perspective, out typeUsage))
{
binding = new ParameterBinding(expression, parameter);
// compute the parameter value during translation since we translate directly
// before evaluating (in other words, the value of the parameter will not change
// between now and the time results are produced)
binding.EvaluateBinding();
return true;
}
// determine if the expression yields an inline ObjectQuery or Expression
object result = ExpressionEvaluator.EvaluateExpression(expression);
ObjectQuery resultQuery = result as ObjectQuery;
if (resultQuery != null)
{
binding = new NestedLogicBinding(expression, result, resultQuery.QueryState.UserSpecifiedMergeOption);
return true;
}
else if (allowLambda && result is LambdaExpression)
{
binding = new NestedLogicBinding(expression, result, null);
return true;
}
}
// doesn't match the pattern
binding = null;
typeUsage = null;
return false;
}
internal static string GenerateParameterName()
{
// To avoid collisions with user parameters (the full set is not
// known at this time) we plug together an 'unlikely' prefix and
// a number.
return String.Format(CultureInfo.InvariantCulture, "{0}{1}",
s_parameterPrefix,
Interlocked.Increment(ref s_parameterNumber));
}
#endregion
#region Nested types
private class NestedLogicBinding : ClosureBinding
{
private MergeOption? _mergeOption;
internal NestedLogicBinding(LinqExpression sourceExpression, object nestedLogic, MergeOption? mergeOption)
: base(sourceExpression)
{
_nestedLogic = nestedLogic;
_mergeOption = mergeOption;
}
private object _nestedLogic;
internal override ClosureBinding CopyToContext(ExpressionConverter context)
{
return this;
}
internal override bool EvaluateBinding()
{
// must recompile entire expression if the sub-expression has changed
object currentLogic = ExpressionEvaluator.EvaluateExpression(_sourceExpression);
if (object.ReferenceEquals(_nestedLogic, currentLogic))
{
// The instances are the same; however, if the nested logic is actually
// an instance of ObjectQuery, then any mutable properties on the instance
// may also have changed. Currently only MergeOption is significant, so it
// must be compared here.
ObjectQuery query = currentLogic as ObjectQuery;
if (query == null)
{
// The nested logic is not an ObjectQuery; simply return false.
return false;
}
// The only way the merge option can change in a way that affects us
// here is if it has been explicitly set using ObjectQuery.MergeOption.
MergeOption? newMergeOption = query.QueryState.UserSpecifiedMergeOption;
if (!newMergeOption.HasValue && !_mergeOption.HasValue)
{
// No difference.
return false;
}
if (newMergeOption.HasValue && _mergeOption.HasValue &&
newMergeOption.Value == _mergeOption.Value)
{
// No difference.
return false;
}
}
return true;
}
internal override LinqExpression Expression
{
get { return _nestedLogic as LinqExpression; }
}
internal override ObjectQuery Query
{
get { return _nestedLogic as ObjectQuery; }
}
internal override ObjectParameter Parameter
{
get { return null; }
}
}
private class ParameterBinding : ClosureBinding
{
internal ParameterBinding(LinqExpression sourceExpression, ObjectParameter parameter)
: base(sourceExpression)
{
_parameter = parameter;
}
private ObjectParameter _parameter;
internal override ClosureBinding CopyToContext(ExpressionConverter context)
{
ObjectParameter targetParameter = null;
if (context.Parameters != null)
{
targetParameter = context.Parameters[_parameter.Name];
}
return new ParameterBinding(_sourceExpression, targetParameter);
}
internal override bool EvaluateBinding()
{
object currentValue = ExpressionEvaluator.EvaluateExpression(_sourceExpression);
_parameter.Value = currentValue;
return false;
}
internal override LinqExpression Expression
{
get { return null; }
}
internal override ObjectQuery Query
{
get { return null; }
}
internal override ObjectParameter Parameter
{
get { return _parameter; }
}
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
//---------------------------------------------------------------------
using System.Collections;
using LinqExpression = System.Linq.Expressions.Expression;
using CqtExpression = System.Data.Common.CommandTrees.DbExpression;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Data.Common.Utils;
using System.Data.Common.CommandTrees;
using System.Globalization;
using System.Data.Metadata.Edm;
using System.Reflection;
using System.Linq;
using System.Threading;
namespace System.Data.Objects.ELinq
{
///
/// Binding between an object parameter or sub-query and LINQ expression that needs to be
/// re-evaluated before executing a query because it is part of the closure.
///
/// Invariants: the binding defines either the Parameter or the Query property, not both.
///
internal abstract class ClosureBinding
{
#region Constructors
private ClosureBinding(LinqExpression sourceExpression)
{
_sourceExpression = sourceExpression;
}
#endregion
#region Fields
private readonly LinqExpression _sourceExpression;
private static readonly string s_parameterPrefix = "p__linq__";
private static long s_parameterNumber;
#endregion
#region Properties
///
/// Gets the query produced by this closure expression. Returns null if no
/// query is produced.
///
internal abstract ObjectQuery Query { get; }
///
/// Gets the expression produced by this closure expression. Returns null if no
/// expression is produced.
///
internal abstract LinqExpression Expression { get; }
///
/// Gets the parameter storing the primitive value produced by this closure expression.
/// Returns null if no primitive value is produced.
///
internal abstract ObjectParameter Parameter { get; }
#endregion
#region Methods
///
/// Evaluates the binding and populates the object parameter value.
///
/// true if the entire expression should be re-evaluated (if a sub-expression has changed);
/// false otherwise
internal abstract bool EvaluateBinding();
internal abstract ClosureBinding CopyToContext(ExpressionConverter context);
internal static bool TryGetTypeUsageForObjectParameter(ObjectParameter parameter, ClrPerspective perspective, out TypeUsage typeUsage)
{
// since ObjectParameters do not allow users to especify 'facets', make
// sure that the parameter typeusage is not populated with the provider
// dafault facet values
if (perspective.TryGetTypeByName(parameter.MappableType.FullName,
false, // bIgnoreCase
out typeUsage) &&
TypeSemantics.IsPrimitiveType(typeUsage))
{
return true;
}
typeUsage = null;
return false;
}
///
/// requires: expression must not be null
/// Attempt to treat the given expression as a supported parameter reference in a closure.
/// Succeeds if the pattern of the expression is precisely Member(Constant), and the member
/// is of primitive type.
///
/// Expression to check.
/// Perspective to use to resolve expression type.
/// Determines whether Lambda sub-expressions are permitted in this context.
/// Closure binding corresponding to the given expression.
/// Type usage for the binding.
/// true if the given expression can be bound
internal static bool TryCreateClosureBinding(LinqExpression expression,
ClrPerspective perspective, bool allowLambda, HashSet closureCandidates, out ClosureBinding binding, out TypeUsage typeUsage)
{
Debug.Assert(null != expression);
if (ExpressionEvaluator.IsExpressionNodeAClosure(expression) &&
closureCandidates.Contains(expression)) // all nodes below it must qualify also
{
ObjectParameter parameter = new ObjectParameter(GenerateParameterName(),
expression.Type);
if(TryGetTypeUsageForObjectParameter(parameter, perspective, out typeUsage))
{
binding = new ParameterBinding(expression, parameter);
// compute the parameter value during translation since we translate directly
// before evaluating (in other words, the value of the parameter will not change
// between now and the time results are produced)
binding.EvaluateBinding();
return true;
}
// determine if the expression yields an inline ObjectQuery or Expression
object result = ExpressionEvaluator.EvaluateExpression(expression);
ObjectQuery resultQuery = result as ObjectQuery;
if (resultQuery != null)
{
binding = new NestedLogicBinding(expression, result, resultQuery.QueryState.UserSpecifiedMergeOption);
return true;
}
else if (allowLambda && result is LambdaExpression)
{
binding = new NestedLogicBinding(expression, result, null);
return true;
}
}
// doesn't match the pattern
binding = null;
typeUsage = null;
return false;
}
internal static string GenerateParameterName()
{
// To avoid collisions with user parameters (the full set is not
// known at this time) we plug together an 'unlikely' prefix and
// a number.
return String.Format(CultureInfo.InvariantCulture, "{0}{1}",
s_parameterPrefix,
Interlocked.Increment(ref s_parameterNumber));
}
#endregion
#region Nested types
private class NestedLogicBinding : ClosureBinding
{
private MergeOption? _mergeOption;
internal NestedLogicBinding(LinqExpression sourceExpression, object nestedLogic, MergeOption? mergeOption)
: base(sourceExpression)
{
_nestedLogic = nestedLogic;
_mergeOption = mergeOption;
}
private object _nestedLogic;
internal override ClosureBinding CopyToContext(ExpressionConverter context)
{
return this;
}
internal override bool EvaluateBinding()
{
// must recompile entire expression if the sub-expression has changed
object currentLogic = ExpressionEvaluator.EvaluateExpression(_sourceExpression);
if (object.ReferenceEquals(_nestedLogic, currentLogic))
{
// The instances are the same; however, if the nested logic is actually
// an instance of ObjectQuery, then any mutable properties on the instance
// may also have changed. Currently only MergeOption is significant, so it
// must be compared here.
ObjectQuery query = currentLogic as ObjectQuery;
if (query == null)
{
// The nested logic is not an ObjectQuery; simply return false.
return false;
}
// The only way the merge option can change in a way that affects us
// here is if it has been explicitly set using ObjectQuery.MergeOption.
MergeOption? newMergeOption = query.QueryState.UserSpecifiedMergeOption;
if (!newMergeOption.HasValue && !_mergeOption.HasValue)
{
// No difference.
return false;
}
if (newMergeOption.HasValue && _mergeOption.HasValue &&
newMergeOption.Value == _mergeOption.Value)
{
// No difference.
return false;
}
}
return true;
}
internal override LinqExpression Expression
{
get { return _nestedLogic as LinqExpression; }
}
internal override ObjectQuery Query
{
get { return _nestedLogic as ObjectQuery; }
}
internal override ObjectParameter Parameter
{
get { return null; }
}
}
private class ParameterBinding : ClosureBinding
{
internal ParameterBinding(LinqExpression sourceExpression, ObjectParameter parameter)
: base(sourceExpression)
{
_parameter = parameter;
}
private ObjectParameter _parameter;
internal override ClosureBinding CopyToContext(ExpressionConverter context)
{
ObjectParameter targetParameter = null;
if (context.Parameters != null)
{
targetParameter = context.Parameters[_parameter.Name];
}
return new ParameterBinding(_sourceExpression, targetParameter);
}
internal override bool EvaluateBinding()
{
object currentValue = ExpressionEvaluator.EvaluateExpression(_sourceExpression);
_parameter.Value = currentValue;
return false;
}
internal override LinqExpression Expression
{
get { return null; }
}
internal override ObjectQuery Query
{
get { return null; }
}
internal override ObjectParameter Parameter
{
get { return _parameter; }
}
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Comparer.cs
- TextSelectionHelper.cs
- WindowsGraphicsWrapper.cs
- NotifyIcon.cs
- ResolveResponse.cs
- IdentifierCreationService.cs
- CultureTableRecord.cs
- SplitterEvent.cs
- DesignerDataStoredProcedure.cs
- HttpCookieCollection.cs
- StateDesignerConnector.cs
- DocumentPageHost.cs
- PreviewPageInfo.cs
- FunctionQuery.cs
- CircleHotSpot.cs
- FunctionImportMapping.ReturnTypeRenameMapping.cs
- AsyncOperation.cs
- GroupBox.cs
- DataControlFieldHeaderCell.cs
- ConfigXmlElement.cs
- XmlValidatingReaderImpl.cs
- Utils.cs
- ShaderRenderModeValidation.cs
- ToolstripProfessionalRenderer.cs
- Int32RectConverter.cs
- NonParentingControl.cs
- MouseActionValueSerializer.cs
- DispatcherExceptionEventArgs.cs
- FormClosingEvent.cs
- CqlErrorHelper.cs
- BooleanAnimationBase.cs
- StringPropertyBuilder.cs
- DateTimeFormatInfoScanner.cs
- dbenumerator.cs
- ConfigurationSettings.cs
- FixedSOMTable.cs
- OracleException.cs
- DbDataRecord.cs
- MatrixStack.cs
- NetNamedPipeSecurityMode.cs
- SecurityPolicySection.cs
- FormatterServices.cs
- MenuItem.cs
- CodeTypeParameter.cs
- MachineKeySection.cs
- StatusBar.cs
- WebBaseEventKeyComparer.cs
- SafeFindHandle.cs
- XmlSchemaAnyAttribute.cs
- SafeArrayTypeMismatchException.cs
- HMACMD5.cs
- FixedFindEngine.cs
- ResourcesBuildProvider.cs
- XsltQilFactory.cs
- TrustManager.cs
- XmlSerializationReader.cs
- ListViewHitTestInfo.cs
- RoleGroupCollection.cs
- SafeNativeMethods.cs
- WebSysDefaultValueAttribute.cs
- CodeEntryPointMethod.cs
- OrderedDictionary.cs
- RouteParameter.cs
- Facet.cs
- TriggerCollection.cs
- Comparer.cs
- XmlLoader.cs
- HierarchicalDataTemplate.cs
- MsmqInputChannel.cs
- EventLogPermissionEntry.cs
- MemberPath.cs
- NumberFunctions.cs
- XmlSchemaAppInfo.cs
- RegexMatch.cs
- InternalPermissions.cs
- DataListItem.cs
- COSERVERINFO.cs
- RelatedImageListAttribute.cs
- ErrorFormatterPage.cs
- ButtonRenderer.cs
- PageSetupDialog.cs
- WizardDesigner.cs
- ListViewItem.cs
- EntityDesignPluralizationHandler.cs
- PerfCounterSection.cs
- StylusEventArgs.cs
- ClientEventManager.cs
- TextBoxAutomationPeer.cs
- RepeaterCommandEventArgs.cs
- Rect3DValueSerializer.cs
- MdImport.cs
- WebHeaderCollection.cs
- TextParaClient.cs
- FlowDocumentPage.cs
- BuildProvidersCompiler.cs
- ObjectListItem.cs
- CultureInfo.cs
- BamlRecordReader.cs
- HttpFileCollectionWrapper.cs
- FaultPropagationRecord.cs