Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / ClosureBinding.cs / 1 / 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
- ObjectItemCollectionAssemblyCacheEntry.cs
- EditorPartChrome.cs
- VectorAnimationUsingKeyFrames.cs
- _UriSyntax.cs
- RootContext.cs
- ToolStripLabel.cs
- CodeTypeReference.cs
- StructuredTypeInfo.cs
- ProxyGenerationError.cs
- RequestUriProcessor.cs
- DataServiceQueryProvider.cs
- AssemblyAttributes.cs
- XmlEntity.cs
- UnauthorizedAccessException.cs
- ObjectIDGenerator.cs
- ProxyHwnd.cs
- DataTable.cs
- XappLauncher.cs
- CodeStatement.cs
- SpellerHighlightLayer.cs
- XmlnsDefinitionAttribute.cs
- EmbeddedMailObjectsCollection.cs
- OleDbInfoMessageEvent.cs
- ActivityBuilderHelper.cs
- RemotingSurrogateSelector.cs
- ResourceReferenceExpressionConverter.cs
- BindableTemplateBuilder.cs
- XPathAncestorIterator.cs
- InvokerUtil.cs
- EntitySetBaseCollection.cs
- TdsParserHelperClasses.cs
- Control.cs
- ListParaClient.cs
- FormViewPageEventArgs.cs
- ConfigurationSettings.cs
- InOutArgument.cs
- CodeGenerator.cs
- ToRequest.cs
- WindowsListViewSubItem.cs
- ObjectComplexPropertyMapping.cs
- DbException.cs
- DataDocumentXPathNavigator.cs
- BinHexEncoder.cs
- WinOEToolBoxItem.cs
- EnumUnknown.cs
- ApplicationFileParser.cs
- ZipIOFileItemStream.cs
- IntSecurity.cs
- CompoundFileReference.cs
- ConsoleCancelEventArgs.cs
- Latin1Encoding.cs
- XPathMultyIterator.cs
- Material.cs
- EpmContentDeSerializerBase.cs
- printdlgexmarshaler.cs
- KeyTimeConverter.cs
- SortedDictionary.cs
- TemplateInstanceAttribute.cs
- MaterialGroup.cs
- XmlQualifiedName.cs
- Dynamic.cs
- PageRequestManager.cs
- TraceEventCache.cs
- NegatedCellConstant.cs
- HttpResponseWrapper.cs
- ToolStripDropTargetManager.cs
- TransactionFlowElement.cs
- QueryCursorEventArgs.cs
- PropertyEmitter.cs
- BinHexEncoder.cs
- WMICapabilities.cs
- PrtCap_Public.cs
- QilNode.cs
- TypeExtensionConverter.cs
- MetadataProperty.cs
- CompilationLock.cs
- CollaborationHelperFunctions.cs
- XmlNode.cs
- ToolBarTray.cs
- AppSettingsExpressionBuilder.cs
- GlyphTypeface.cs
- FieldToken.cs
- MatrixConverter.cs
- StorageInfo.cs
- BoundPropertyEntry.cs
- MediaEntryAttribute.cs
- Visual.cs
- SimpleApplicationHost.cs
- WebHeaderCollection.cs
- HealthMonitoringSectionHelper.cs
- DataTableMapping.cs
- ContractMethodInfo.cs
- MenuScrollingVisibilityConverter.cs
- StringConverter.cs
- XmlSchemaGroup.cs
- ExtensibleClassFactory.cs
- DataRowComparer.cs
- SafeCryptHandles.cs
- ImageBrush.cs
- FloatUtil.cs