Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / MaterializeFromAtom.cs / 1305376 / MaterializeFromAtom.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //// materialize objects from an xml stream // //--------------------------------------------------------------------- namespace System.Data.Services.Client { #region Namespaces. using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Xml; using System.Xml.Linq; using System.Text; using System.Linq.Expressions; #endregion Namespaces. ////// Use this class to materialize objects from an application/atom+xml stream. /// internal class MaterializeAtom : IDisposable, IEnumerable, IEnumerator { ///MergeOption captured from context so its static for the entire materialization internal readonly MergeOption MergeOptionValue; #region Private fields. ///Row count value representing the initial state (-1) private const long CountStateInitial = -1; ///Row count value representing the failure state (-2) private const long CountStateFailure = -2; ///Options when deserializing properties to the target type. private readonly bool ignoreMissingProperties; ///Backreference to the context to allow type resolution. private readonly DataServiceContext context; ///base type of the object to create from the stream. private readonly Type elementType; ///when materializing a known type (like string) ///<property> text-value </property> private readonly bool expectingSingleValue; ///Materializer from which instances are read. ////// The log for the materializer stores all changes for the /// associated data context. /// private readonly AtomMaterializer materializer; ///Parser used by materializer. ///Odd thing to have, only here to force a lookahead for inline elements. private readonly AtomParser parser; ///source reader (may be running on top of a buffer or be the real reader) private XmlReader reader; ///untyped current object private object current; ///has GetEnumerator been called? private bool calledGetEnumerator; ///The count tag's value, if requested private long countValue; ///Whether anything has been read. private bool moved; ////// output writer, set using reflection /// #if DEBUG && !ASTORIA_LIGHT private System.IO.TextWriter writer = new System.IO.StringWriter(System.Globalization.CultureInfo.InvariantCulture); #else #pragma warning disable 649 private System.IO.TextWriter writer; #pragma warning restore 649 #endif #endregion Private fields. ////// constructor /// /// originating context /// reader /// Query components (projection, expected type) /// Projection plan (if compiled in an earlier query). /// merge option to use for this materialization pass internal MaterializeAtom(DataServiceContext context, XmlReader reader, QueryComponents queryComponents, ProjectionPlan plan, MergeOption mergeOption) { Debug.Assert(queryComponents != null, "queryComponents != null"); this.context = context; this.elementType = queryComponents.LastSegmentType; this.MergeOptionValue = mergeOption; this.ignoreMissingProperties = context.IgnoreMissingProperties; this.reader = (reader == null) ? null : new System.Data.Services.Client.Xml.XmlAtomErrorReader(reader); this.countValue = CountStateInitial; this.expectingSingleValue = ClientConvert.IsKnownNullableType(elementType); Debug.Assert(reader != null, "Materializer reader is null! Did you mean to use Materializer.ResultsWrapper/EmptyResults?"); // NOTE: dataNamespace is used for reference equality, and while it looks like // a variable, it appears that it will only get set to XmlConstants.DataWebNamespace // at runtime. Therefore we remove string dataNamespace as a field here. // this.dataNamespace = reader != null ? reader.Settings.NameTable.Add(context.DataNamespace) : null; reader.Settings.NameTable.Add(context.DataNamespace); string typeScheme = this.context.TypeScheme.OriginalString; this.parser = new AtomParser(this.reader, AtomParser.XElementBuilderCallback, typeScheme, context.DataNamespace); AtomMaterializerLog log = new AtomMaterializerLog(this.context, mergeOption); Type implementationType; Type materializerType = GetTypeForMaterializer(this.expectingSingleValue, this.elementType, out implementationType); this.materializer = new AtomMaterializer(parser, context, materializerType, this.ignoreMissingProperties, mergeOption, log, this.MaterializedObjectCallback, queryComponents, plan); } private void MaterializedObjectCallback(object tag, object entity) { Debug.Assert(tag != null, "tag != null"); Debug.Assert(entity != null, "entity != null"); XElement data = (XElement)tag; if (this.context.HasReadingEntityHandlers) { XmlUtil.RemoveDuplicateNamespaceAttributes(data); this.context.FireReadingEntityEvent(entity, data); } } ////// Private internal constructor used for creating empty wrapper. /// private MaterializeAtom() { } ////// DO NOT USE - this is a private hook for client unit tests to construct materializers /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] private MaterializeAtom(DataServiceContext context, XmlReader reader, Type type, MergeOption mergeOption) : this(context, reader, new QueryComponents(null, Util.DataServiceVersionEmpty, type, null, null), null, mergeOption) { } #region Current ///Loosely typed current object property. ////// The value should be of the right type, as the materializer takes the /// expected type into account. /// public object Current { get { object currentValue = this.current; return currentValue; } } #endregion ////// A materializer for empty results /// internal static MaterializeAtom EmptyResults { get { return new ResultsWrapper(null, null); } } ////// Returns true, if the materialize atom has empty results, because of /// IgnoreResourceNotFoundException flag set in context /// internal bool IsEmptyResults { get { return this.reader == null; } } ////// The context object this materializer belongs to /// internal DataServiceContext Context { get { return this.context; } } #region IDisposable ////// dispose /// public void Dispose() { this.current = null; if (null != this.reader) { ((IDisposable)this.reader).Dispose(); } if (null != this.writer) { this.writer.Dispose(); } GC.SuppressFinalize(this); } #endregion #region IEnumerable ////// as IEnumerable /// ///this public virtual IEnumerator GetEnumerator() { this.CheckGetEnumerator(); return this; } #endregion private static Type GetTypeForMaterializer(bool expectingSingleValue, Type elementType, out Type implementationType) { if (!expectingSingleValue && typeof(IEnumerable).IsAssignableFrom(elementType)) { implementationType = ClientType.GetImplementationType(elementType, typeof(ICollection<>)); if (implementationType != null) { Type expectedType = implementationType.GetGenericArguments()[0]; // already know its IList<> return expectedType; } } implementationType = null; return elementType; } ////// Creates the next object from the stream. /// ///false if stream is finished public bool MoveNext() { bool applying = this.context.ApplyingChanges; try { this.context.ApplyingChanges = true; return this.MoveNextInternal(); } finally { this.context.ApplyingChanges = applying; } } ////// Creates the next object from the stream. /// ///false if stream is finished private bool MoveNextInternal() { // For empty results, just return false. if (this.reader == null) { Debug.Assert(this.current == null, "this.current == null -- otherwise this.reader should have some value."); return false; } this.current = null; this.materializer.Log.Clear(); bool result = false; Type implementationType; GetTypeForMaterializer(this.expectingSingleValue, this.elementType, out implementationType); if (implementationType != null) { if (this.moved) { return false; } Type expectedType = implementationType.GetGenericArguments()[0]; // already know its IList<> implementationType = this.elementType; if (implementationType.IsInterface) { implementationType = typeof(System.Collections.ObjectModel.Collection<>).MakeGenericType(expectedType); } IList list = (IList)Activator.CreateInstance(implementationType); while (this.materializer.Read()) { this.moved = true; list.Add(this.materializer.CurrentValue); } this.current = list; result = true; } if (null == this.current) { if (this.expectingSingleValue && this.moved) { result = false; } else { result = this.materializer.Read(); if (result) { this.current = this.materializer.CurrentValue; } this.moved = true; } } this.materializer.Log.ApplyToContext(); return result; } ////// Not supported. /// ///Always thrown void System.Collections.IEnumerator.Reset() { throw Error.NotSupported(); } ////// Creates materializer for results /// /// the results to wrap ///a new materializer internal static MaterializeAtom CreateWrapper(IEnumerable results) { return new ResultsWrapper(results, null); } ///Creates a materializer for partial result sets. /// The current page of results /// The continuation for the results. ///A new materializer. internal static MaterializeAtom CreateWrapper(IEnumerable results, DataServiceQueryContinuation continuation) { return new ResultsWrapper(results, continuation); } ///set the inserted object expected in the response /// object being inserted that the response is looking for internal void SetInsertingObject(object addedObject) { this.materializer.TargetInstance = addedObject; } internal static void SkipToEnd(XmlReader reader) { Debug.Assert(reader != null, "reader != null"); Debug.Assert(reader.NodeType == XmlNodeType.Element, "reader.NodeType == XmlNodeType.Element"); if (reader.IsEmptyElement) { return; } int readerDepth = reader.Depth; while (reader.Read()) { if (reader.NodeType == XmlNodeType.EndElement && reader.Depth == readerDepth) { return; } } } ////// The count tag's value, if requested /// ///The count value returned from the server internal long CountValue() { if (this.countValue == CountStateInitial) { this.ReadCountValue(); } else if (this.countValue == CountStateFailure) { throw new InvalidOperationException(Strings.MaterializeFromAtom_CountNotPresent); } return this.countValue; } ////// Returns the next link URI for the collection key /// /// The collection for which the Uri is returned, or null, if the top level link is to be returned ///An Uri pointing to the next page for the collection internal virtual DataServiceQueryContinuation GetContinuation(IEnumerable key) { Debug.Assert(this.materializer != null, "Materializer is null!"); DataServiceQueryContinuation result; if (key == null) { if ((this.expectingSingleValue && !this.moved) || (!this.expectingSingleValue && !this.materializer.IsEndOfStream)) { // expectingSingleValue && !moved : haven't started parsing single value (single value should not have next link anyway) // !expectingSingleValue && !IsEndOfStream : collection type feed did not finish parsing yet throw new InvalidOperationException(Strings.MaterializeFromAtom_TopLevelLinkNotAvailable); } // we have already moved to the end of stream // are we singleton or just an entry? if (this.expectingSingleValue || this.materializer.CurrentFeed == null) { result = null; } else { // DEVNOTE([....]): The next link uri should never be edited by the client, and therefore it must be absolute result = DataServiceQueryContinuation.Create( this.materializer.CurrentFeed.NextLink, this.materializer.MaterializeEntryPlan); } } else { if (!this.materializer.NextLinkTable.TryGetValue(key, out result)) { // someone has asked for a collection that's "out of scope" or doesn't exist throw new ArgumentException(Strings.MaterializeFromAtom_CollectionKeyNotPresentInLinkTable); } } return result; } ///verify the GetEnumerator can only be called once private void CheckGetEnumerator() { if (this.calledGetEnumerator) { throw Error.NotSupported(Strings.Deserialize_GetEnumerator); } this.calledGetEnumerator = true; } ////// read the m2:count tag in the feed /// private void ReadCountValue() { Debug.Assert(this.countValue == CountStateInitial, "Count value is not in the initial state"); if (this.materializer.CurrentFeed != null && this.materializer.CurrentFeed.Count.HasValue) { this.countValue = this.materializer.CurrentFeed.Count.Value; return; } // find the first element tag while (this.reader.NodeType != XmlNodeType.Element && this.reader.Read()) { } if (this.reader.EOF) { throw new InvalidOperationException(Strings.MaterializeFromAtom_CountNotPresent); } // the tag Should only beor tag: Debug.Assert( (Util.AreSame(XmlConstants.AtomNamespace, this.reader.NamespaceURI) && Util.AreSame(XmlConstants.AtomFeedElementName, this.reader.LocalName)) || (Util.AreSame(XmlConstants.DataWebNamespace, this.reader.NamespaceURI) && Util.AreSame(XmlConstants.LinkCollectionElementName, this.reader.LocalName)), " or tag expected"); // Create the XElement for look-ahead // DEVNOTE([....]): // This is not streaming friendly! XElement element = XElement.Load(this.reader); this.reader.Close(); // Read the count value from the xelement XElement countNode = element.Descendants(XNamespace.Get(XmlConstants.DataWebMetadataNamespace) + XmlConstants.RowCountElement).FirstOrDefault(); if (countNode == null) { throw new InvalidOperationException(Strings.MaterializeFromAtom_CountNotPresent); } else { if (!long.TryParse(countNode.Value, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out this.countValue)) { throw new FormatException(Strings.MaterializeFromAtom_CountFormatError); } if (this.countValue < 0) { throw new FormatException(Strings.MaterializeFromAtom_CountFormatError); } } this.reader = new System.Data.Services.Client.Xml.XmlAtomErrorReader(element.CreateReader()); this.parser.ReplaceReader(this.reader); } /// /// Gets the /// String with type name to check. /// Context in which type is being resolved. /// Expected type for the name. /// /// Whether to check that a user-overriden type is assignable to a /// variable of typefor the (potentially /// user-callback-resolved) type name. /// . /// /// The internal static ClientType GetEntryClientType(string typeName, DataServiceContext context, Type expectedType, bool checkAssignable) { Debug.Assert(context != null, "context != null"); Type resolvedType = context.ResolveTypeFromName(typeName, expectedType, checkAssignable); ClientType result = ClientType.Create(resolvedType); Debug.Assert(result != null, "result != null -- otherwise ClientType.Create returned null"); return result; } internal static string ReadElementString(XmlReader reader, bool checkNullAttribute) { Debug.Assert(reader != null, "reader != null"); Debug.Assert( reader.NodeType == XmlNodeType.Element, "reader.NodeType == XmlNodeType.Element -- otherwise caller is confused as to where the reader is"); string result = null; bool empty = checkNullAttribute && !Util.DoesNullAttributeSayTrue(reader); if (reader.IsEmptyElement) { return (empty ? String.Empty : null); } while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.EndElement: return result ?? (empty ? String.Empty : null); case XmlNodeType.CDATA: case XmlNodeType.Text: case XmlNodeType.SignificantWhitespace: if (null != result) { throw Error.InvalidOperation(Strings.Deserialize_MixedTextWithComment); } result = reader.Value; break; case XmlNodeType.Comment: case XmlNodeType.Whitespace: break; #region XmlNodeType error case XmlNodeType.Element: goto default; default: throw Error.InvalidOperation(Strings.Deserialize_ExpectingSimpleValue); #endregion } } // xml ended before EndElement? throw Error.InvalidOperation(Strings.Deserialize_ExpectingSimpleValue); } ///for the given type name. /// Private type to wrap partial (paged) results and make it look like standard materialized results. /// private class ResultsWrapper : MaterializeAtom { #region Private fields. ///The results to wrap private readonly IEnumerable results; ///A continuation to the next page of results. private readonly DataServiceQueryContinuation continuation; #endregion Private fields. ////// Creates a wrapper for raw results /// /// the results to wrap /// The continuation for this query. internal ResultsWrapper(IEnumerable results, DataServiceQueryContinuation continuation) { this.results = results ?? new object[0]; this.continuation = continuation; } ////// Get the next link to the result set /// /// When equals to null, returns the next link associated with this collection. Otherwise throws InvalidOperationException. ///The continuation for this query. internal override DataServiceQueryContinuation GetContinuation(IEnumerable key) { if (key == null) { return this.continuation; } else { throw new InvalidOperationException(Strings.MaterializeFromAtom_GetNestLinkForFlatCollection); } } ////// Gets Enumerator for wrapped results. /// ///IEnumerator for results public override IEnumerator GetEnumerator() { return this.results.GetEnumerator(); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //// materialize objects from an xml stream // //--------------------------------------------------------------------- namespace System.Data.Services.Client { #region Namespaces. using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Xml; using System.Xml.Linq; using System.Text; using System.Linq.Expressions; #endregion Namespaces. ////// Use this class to materialize objects from an application/atom+xml stream. /// internal class MaterializeAtom : IDisposable, IEnumerable, IEnumerator { ///MergeOption captured from context so its static for the entire materialization internal readonly MergeOption MergeOptionValue; #region Private fields. ///Row count value representing the initial state (-1) private const long CountStateInitial = -1; ///Row count value representing the failure state (-2) private const long CountStateFailure = -2; ///Options when deserializing properties to the target type. private readonly bool ignoreMissingProperties; ///Backreference to the context to allow type resolution. private readonly DataServiceContext context; ///base type of the object to create from the stream. private readonly Type elementType; ///when materializing a known type (like string) ///<property> text-value </property> private readonly bool expectingSingleValue; ///Materializer from which instances are read. ////// The log for the materializer stores all changes for the /// associated data context. /// private readonly AtomMaterializer materializer; ///Parser used by materializer. ///Odd thing to have, only here to force a lookahead for inline elements. private readonly AtomParser parser; ///source reader (may be running on top of a buffer or be the real reader) private XmlReader reader; ///untyped current object private object current; ///has GetEnumerator been called? private bool calledGetEnumerator; ///The count tag's value, if requested private long countValue; ///Whether anything has been read. private bool moved; ////// output writer, set using reflection /// #if DEBUG && !ASTORIA_LIGHT private System.IO.TextWriter writer = new System.IO.StringWriter(System.Globalization.CultureInfo.InvariantCulture); #else #pragma warning disable 649 private System.IO.TextWriter writer; #pragma warning restore 649 #endif #endregion Private fields. ////// constructor /// /// originating context /// reader /// Query components (projection, expected type) /// Projection plan (if compiled in an earlier query). /// merge option to use for this materialization pass internal MaterializeAtom(DataServiceContext context, XmlReader reader, QueryComponents queryComponents, ProjectionPlan plan, MergeOption mergeOption) { Debug.Assert(queryComponents != null, "queryComponents != null"); this.context = context; this.elementType = queryComponents.LastSegmentType; this.MergeOptionValue = mergeOption; this.ignoreMissingProperties = context.IgnoreMissingProperties; this.reader = (reader == null) ? null : new System.Data.Services.Client.Xml.XmlAtomErrorReader(reader); this.countValue = CountStateInitial; this.expectingSingleValue = ClientConvert.IsKnownNullableType(elementType); Debug.Assert(reader != null, "Materializer reader is null! Did you mean to use Materializer.ResultsWrapper/EmptyResults?"); // NOTE: dataNamespace is used for reference equality, and while it looks like // a variable, it appears that it will only get set to XmlConstants.DataWebNamespace // at runtime. Therefore we remove string dataNamespace as a field here. // this.dataNamespace = reader != null ? reader.Settings.NameTable.Add(context.DataNamespace) : null; reader.Settings.NameTable.Add(context.DataNamespace); string typeScheme = this.context.TypeScheme.OriginalString; this.parser = new AtomParser(this.reader, AtomParser.XElementBuilderCallback, typeScheme, context.DataNamespace); AtomMaterializerLog log = new AtomMaterializerLog(this.context, mergeOption); Type implementationType; Type materializerType = GetTypeForMaterializer(this.expectingSingleValue, this.elementType, out implementationType); this.materializer = new AtomMaterializer(parser, context, materializerType, this.ignoreMissingProperties, mergeOption, log, this.MaterializedObjectCallback, queryComponents, plan); } private void MaterializedObjectCallback(object tag, object entity) { Debug.Assert(tag != null, "tag != null"); Debug.Assert(entity != null, "entity != null"); XElement data = (XElement)tag; if (this.context.HasReadingEntityHandlers) { XmlUtil.RemoveDuplicateNamespaceAttributes(data); this.context.FireReadingEntityEvent(entity, data); } } ////// Private internal constructor used for creating empty wrapper. /// private MaterializeAtom() { } ////// DO NOT USE - this is a private hook for client unit tests to construct materializers /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] private MaterializeAtom(DataServiceContext context, XmlReader reader, Type type, MergeOption mergeOption) : this(context, reader, new QueryComponents(null, Util.DataServiceVersionEmpty, type, null, null), null, mergeOption) { } #region Current ///Loosely typed current object property. ////// The value should be of the right type, as the materializer takes the /// expected type into account. /// public object Current { get { object currentValue = this.current; return currentValue; } } #endregion ////// A materializer for empty results /// internal static MaterializeAtom EmptyResults { get { return new ResultsWrapper(null, null); } } ////// Returns true, if the materialize atom has empty results, because of /// IgnoreResourceNotFoundException flag set in context /// internal bool IsEmptyResults { get { return this.reader == null; } } ////// The context object this materializer belongs to /// internal DataServiceContext Context { get { return this.context; } } #region IDisposable ////// dispose /// public void Dispose() { this.current = null; if (null != this.reader) { ((IDisposable)this.reader).Dispose(); } if (null != this.writer) { this.writer.Dispose(); } GC.SuppressFinalize(this); } #endregion #region IEnumerable ////// as IEnumerable /// ///this public virtual IEnumerator GetEnumerator() { this.CheckGetEnumerator(); return this; } #endregion private static Type GetTypeForMaterializer(bool expectingSingleValue, Type elementType, out Type implementationType) { if (!expectingSingleValue && typeof(IEnumerable).IsAssignableFrom(elementType)) { implementationType = ClientType.GetImplementationType(elementType, typeof(ICollection<>)); if (implementationType != null) { Type expectedType = implementationType.GetGenericArguments()[0]; // already know its IList<> return expectedType; } } implementationType = null; return elementType; } ////// Creates the next object from the stream. /// ///false if stream is finished public bool MoveNext() { bool applying = this.context.ApplyingChanges; try { this.context.ApplyingChanges = true; return this.MoveNextInternal(); } finally { this.context.ApplyingChanges = applying; } } ////// Creates the next object from the stream. /// ///false if stream is finished private bool MoveNextInternal() { // For empty results, just return false. if (this.reader == null) { Debug.Assert(this.current == null, "this.current == null -- otherwise this.reader should have some value."); return false; } this.current = null; this.materializer.Log.Clear(); bool result = false; Type implementationType; GetTypeForMaterializer(this.expectingSingleValue, this.elementType, out implementationType); if (implementationType != null) { if (this.moved) { return false; } Type expectedType = implementationType.GetGenericArguments()[0]; // already know its IList<> implementationType = this.elementType; if (implementationType.IsInterface) { implementationType = typeof(System.Collections.ObjectModel.Collection<>).MakeGenericType(expectedType); } IList list = (IList)Activator.CreateInstance(implementationType); while (this.materializer.Read()) { this.moved = true; list.Add(this.materializer.CurrentValue); } this.current = list; result = true; } if (null == this.current) { if (this.expectingSingleValue && this.moved) { result = false; } else { result = this.materializer.Read(); if (result) { this.current = this.materializer.CurrentValue; } this.moved = true; } } this.materializer.Log.ApplyToContext(); return result; } ////// Not supported. /// ///Always thrown void System.Collections.IEnumerator.Reset() { throw Error.NotSupported(); } ////// Creates materializer for results /// /// the results to wrap ///a new materializer internal static MaterializeAtom CreateWrapper(IEnumerable results) { return new ResultsWrapper(results, null); } ///Creates a materializer for partial result sets. /// The current page of results /// The continuation for the results. ///A new materializer. internal static MaterializeAtom CreateWrapper(IEnumerable results, DataServiceQueryContinuation continuation) { return new ResultsWrapper(results, continuation); } ///set the inserted object expected in the response /// object being inserted that the response is looking for internal void SetInsertingObject(object addedObject) { this.materializer.TargetInstance = addedObject; } internal static void SkipToEnd(XmlReader reader) { Debug.Assert(reader != null, "reader != null"); Debug.Assert(reader.NodeType == XmlNodeType.Element, "reader.NodeType == XmlNodeType.Element"); if (reader.IsEmptyElement) { return; } int readerDepth = reader.Depth; while (reader.Read()) { if (reader.NodeType == XmlNodeType.EndElement && reader.Depth == readerDepth) { return; } } } ////// The count tag's value, if requested /// ///The count value returned from the server internal long CountValue() { if (this.countValue == CountStateInitial) { this.ReadCountValue(); } else if (this.countValue == CountStateFailure) { throw new InvalidOperationException(Strings.MaterializeFromAtom_CountNotPresent); } return this.countValue; } ////// Returns the next link URI for the collection key /// /// The collection for which the Uri is returned, or null, if the top level link is to be returned ///An Uri pointing to the next page for the collection internal virtual DataServiceQueryContinuation GetContinuation(IEnumerable key) { Debug.Assert(this.materializer != null, "Materializer is null!"); DataServiceQueryContinuation result; if (key == null) { if ((this.expectingSingleValue && !this.moved) || (!this.expectingSingleValue && !this.materializer.IsEndOfStream)) { // expectingSingleValue && !moved : haven't started parsing single value (single value should not have next link anyway) // !expectingSingleValue && !IsEndOfStream : collection type feed did not finish parsing yet throw new InvalidOperationException(Strings.MaterializeFromAtom_TopLevelLinkNotAvailable); } // we have already moved to the end of stream // are we singleton or just an entry? if (this.expectingSingleValue || this.materializer.CurrentFeed == null) { result = null; } else { // DEVNOTE([....]): The next link uri should never be edited by the client, and therefore it must be absolute result = DataServiceQueryContinuation.Create( this.materializer.CurrentFeed.NextLink, this.materializer.MaterializeEntryPlan); } } else { if (!this.materializer.NextLinkTable.TryGetValue(key, out result)) { // someone has asked for a collection that's "out of scope" or doesn't exist throw new ArgumentException(Strings.MaterializeFromAtom_CollectionKeyNotPresentInLinkTable); } } return result; } ///verify the GetEnumerator can only be called once private void CheckGetEnumerator() { if (this.calledGetEnumerator) { throw Error.NotSupported(Strings.Deserialize_GetEnumerator); } this.calledGetEnumerator = true; } ////// read the m2:count tag in the feed /// private void ReadCountValue() { Debug.Assert(this.countValue == CountStateInitial, "Count value is not in the initial state"); if (this.materializer.CurrentFeed != null && this.materializer.CurrentFeed.Count.HasValue) { this.countValue = this.materializer.CurrentFeed.Count.Value; return; } // find the first element tag while (this.reader.NodeType != XmlNodeType.Element && this.reader.Read()) { } if (this.reader.EOF) { throw new InvalidOperationException(Strings.MaterializeFromAtom_CountNotPresent); } // the tag Should only beor tag: Debug.Assert( (Util.AreSame(XmlConstants.AtomNamespace, this.reader.NamespaceURI) && Util.AreSame(XmlConstants.AtomFeedElementName, this.reader.LocalName)) || (Util.AreSame(XmlConstants.DataWebNamespace, this.reader.NamespaceURI) && Util.AreSame(XmlConstants.LinkCollectionElementName, this.reader.LocalName)), " or tag expected"); // Create the XElement for look-ahead // DEVNOTE([....]): // This is not streaming friendly! XElement element = XElement.Load(this.reader); this.reader.Close(); // Read the count value from the xelement XElement countNode = element.Descendants(XNamespace.Get(XmlConstants.DataWebMetadataNamespace) + XmlConstants.RowCountElement).FirstOrDefault(); if (countNode == null) { throw new InvalidOperationException(Strings.MaterializeFromAtom_CountNotPresent); } else { if (!long.TryParse(countNode.Value, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out this.countValue)) { throw new FormatException(Strings.MaterializeFromAtom_CountFormatError); } if (this.countValue < 0) { throw new FormatException(Strings.MaterializeFromAtom_CountFormatError); } } this.reader = new System.Data.Services.Client.Xml.XmlAtomErrorReader(element.CreateReader()); this.parser.ReplaceReader(this.reader); } /// /// Gets the /// String with type name to check. /// Context in which type is being resolved. /// Expected type for the name. /// /// Whether to check that a user-overriden type is assignable to a /// variable of typefor the (potentially /// user-callback-resolved) type name. /// . /// /// The internal static ClientType GetEntryClientType(string typeName, DataServiceContext context, Type expectedType, bool checkAssignable) { Debug.Assert(context != null, "context != null"); Type resolvedType = context.ResolveTypeFromName(typeName, expectedType, checkAssignable); ClientType result = ClientType.Create(resolvedType); Debug.Assert(result != null, "result != null -- otherwise ClientType.Create returned null"); return result; } internal static string ReadElementString(XmlReader reader, bool checkNullAttribute) { Debug.Assert(reader != null, "reader != null"); Debug.Assert( reader.NodeType == XmlNodeType.Element, "reader.NodeType == XmlNodeType.Element -- otherwise caller is confused as to where the reader is"); string result = null; bool empty = checkNullAttribute && !Util.DoesNullAttributeSayTrue(reader); if (reader.IsEmptyElement) { return (empty ? String.Empty : null); } while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.EndElement: return result ?? (empty ? String.Empty : null); case XmlNodeType.CDATA: case XmlNodeType.Text: case XmlNodeType.SignificantWhitespace: if (null != result) { throw Error.InvalidOperation(Strings.Deserialize_MixedTextWithComment); } result = reader.Value; break; case XmlNodeType.Comment: case XmlNodeType.Whitespace: break; #region XmlNodeType error case XmlNodeType.Element: goto default; default: throw Error.InvalidOperation(Strings.Deserialize_ExpectingSimpleValue); #endregion } } // xml ended before EndElement? throw Error.InvalidOperation(Strings.Deserialize_ExpectingSimpleValue); } ///for the given type name. /// Private type to wrap partial (paged) results and make it look like standard materialized results. /// private class ResultsWrapper : MaterializeAtom { #region Private fields. ///The results to wrap private readonly IEnumerable results; ///A continuation to the next page of results. private readonly DataServiceQueryContinuation continuation; #endregion Private fields. ////// Creates a wrapper for raw results /// /// the results to wrap /// The continuation for this query. internal ResultsWrapper(IEnumerable results, DataServiceQueryContinuation continuation) { this.results = results ?? new object[0]; this.continuation = continuation; } ////// Get the next link to the result set /// /// When equals to null, returns the next link associated with this collection. Otherwise throws InvalidOperationException. ///The continuation for this query. internal override DataServiceQueryContinuation GetContinuation(IEnumerable key) { if (key == null) { return this.continuation; } else { throw new InvalidOperationException(Strings.MaterializeFromAtom_GetNestLinkForFlatCollection); } } ////// Gets Enumerator for wrapped results. /// ///IEnumerator for results public override IEnumerator GetEnumerator() { return this.results.GetEnumerator(); } } } } // 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
- ScrollChrome.cs
- BooleanExpr.cs
- Claim.cs
- RightNameExpirationInfoPair.cs
- BmpBitmapEncoder.cs
- Repeater.cs
- AsyncOperationContext.cs
- HashCryptoHandle.cs
- xml.cs
- StorageEntitySetMapping.cs
- XamlTemplateSerializer.cs
- ClientConfigurationHost.cs
- ColorComboBox.cs
- LinqExpressionNormalizer.cs
- WasEndpointConfigContainer.cs
- ClosureBinding.cs
- BrowserCapabilitiesCompiler.cs
- XmlWrappingReader.cs
- CmsInterop.cs
- DictionarySectionHandler.cs
- Decorator.cs
- login.cs
- InfiniteTimeSpanConverter.cs
- ElementProxy.cs
- AutomationIdentifierGuids.cs
- ItemContainerGenerator.cs
- VisualSerializer.cs
- TextTreeDeleteContentUndoUnit.cs
- AmbiguousMatchException.cs
- StringSource.cs
- ValidatorCompatibilityHelper.cs
- FileClassifier.cs
- TreeNodeMouseHoverEvent.cs
- SpanIndex.cs
- EqualityArray.cs
- State.cs
- SQLBytesStorage.cs
- CryptoConfig.cs
- CqlBlock.cs
- ACL.cs
- DataGridLengthConverter.cs
- ChannelBase.cs
- QilStrConcat.cs
- NameTable.cs
- PageSetupDialog.cs
- OleCmdHelper.cs
- TextDecorationCollection.cs
- Odbc32.cs
- SimplePropertyEntry.cs
- WebPartHeaderCloseVerb.cs
- ItemDragEvent.cs
- SymbolMethod.cs
- brushes.cs
- TypeUtil.cs
- ToolStripHighContrastRenderer.cs
- XmlSigningNodeWriter.cs
- ContentElementAutomationPeer.cs
- XmlSiteMapProvider.cs
- InArgumentConverter.cs
- HtmlLinkAdapter.cs
- ImageConverter.cs
- Literal.cs
- PixelShader.cs
- TextCompositionManager.cs
- MinMaxParagraphWidth.cs
- XmlElementCollection.cs
- PropertyItemInternal.cs
- InputProcessorProfilesLoader.cs
- DrawingContextWalker.cs
- DbgCompiler.cs
- EntityDataSourceSelectingEventArgs.cs
- OutOfProcStateClientManager.cs
- GrammarBuilderBase.cs
- ConcatQueryOperator.cs
- ScrollItemPatternIdentifiers.cs
- PointCollectionConverter.cs
- UpDownBaseDesigner.cs
- CodeVariableDeclarationStatement.cs
- MouseCaptureWithinProperty.cs
- DynamicValidator.cs
- ConfigurationConverterBase.cs
- ShortcutKeysEditor.cs
- Function.cs
- DataGridViewLayoutData.cs
- EntityContainerAssociationSet.cs
- TargetControlTypeCache.cs
- Convert.cs
- DictionaryContent.cs
- RegionData.cs
- Control.cs
- SafeTimerHandle.cs
- LinearQuaternionKeyFrame.cs
- WmiInstallComponent.cs
- StrokeNodeData.cs
- EntityModelSchemaGenerator.cs
- PenThread.cs
- ByteAnimation.cs
- OperationPickerDialog.cs
- BamlBinaryReader.cs
- streamingZipPartStream.cs