System.Xml.Xsl.IlGen.XmlILVisitor.NestedVisitEnsureCache C# (CSharp) Method

NestedVisitEnsureCache() private method

Generate code for the QilExpression node and ensure that results are fully cached as an XmlQuerySequence. All results should be converted to "itemStorageType" before being added to the cache.
private NestedVisitEnsureCache ( QilNode nd, Type itemStorageType ) : void
nd QilNode
itemStorageType System.Type
return void
        private void NestedVisitEnsureCache(QilNode nd, Type itemStorageType) {
            Debug.Assert(!XmlILConstructInfo.Read(nd).PushToWriterLast);
            bool cachesResult = CachesResult(nd);
            LocalBuilder locCache;
            Label lblOnEnd = this.helper.DefineLabel();
            Type cacheType;
            XmlILStorageMethods methods;

            // If bound expression will already be cached correctly, then don't create an XmlQuerySequence
            if (cachesResult) {
                StartNestedIterator(nd);
                Visit(nd);
                EndNestedIterator(nd);
                this.iterCurr.Storage = this.iterNested.Storage;
                Debug.Assert(this.iterCurr.Storage.IsCached, "Expression result should be cached.  CachesResult() might have a bug in it.");

                // If type of items in the cache matches "itemStorageType", then done
                if (this.iterCurr.Storage.ItemStorageType == itemStorageType)
                    return;

                // If the cache has navigators in it, or if converting to a cache of navigators, then EnsureItemStorageType
                // can directly convert without needing to create a new cache.
                if (this.iterCurr.Storage.ItemStorageType == typeof(XPathNavigator) || itemStorageType == typeof(XPathNavigator)) {
                    this.iterCurr.EnsureItemStorageType(nd.XmlType, itemStorageType);
                    return;
                }

                this.iterCurr.EnsureNoStack("$$$cacheResult");
            }

            // Always store navigators in XmlQueryNodeSequence (which implements IList<XPathItem>)
            cacheType = (GetItemStorageType(nd) == typeof(XPathNavigator)) ? typeof(XPathNavigator) : itemStorageType;

            // XmlQuerySequence<T> cache;
            methods = XmlILMethods.StorageMethods[cacheType];
            locCache = this.helper.DeclareLocal("$$$cache", methods.SeqType);
            this.helper.Emit(OpCodes.Ldloc, locCache);

            // Special case non-navigator singletons to use overload of CreateOrReuse
            if (nd.XmlType.IsSingleton) {
                // cache = XmlQuerySequence.CreateOrReuse(cache, item);
                NestedVisitEnsureStack(nd, cacheType, false);
                this.helper.CallToken(methods.SeqReuseSgl);
                this.helper.Emit(OpCodes.Stloc, locCache);
            }
            else {
                // XmlQuerySequence<T> cache;
                // cache = XmlQuerySequence.CreateOrReuse(cache);
                this.helper.CallToken(methods.SeqReuse);
                this.helper.Emit(OpCodes.Stloc, locCache);
                this.helper.Emit(OpCodes.Ldloc, locCache);

                StartNestedIterator(nd, lblOnEnd);

                if (cachesResult)
                    this.iterCurr.Storage = this.iterCurr.ParentIterator.Storage;
                else
                    Visit(nd);

                // cache.Add(item);
                this.iterCurr.EnsureItemStorageType(nd.XmlType, cacheType);
                this.iterCurr.EnsureStackNoCache();
                this.helper.Call(methods.SeqAdd);
                this.helper.Emit(OpCodes.Ldloc, locCache);

                // }
                this.iterCurr.LoopToEnd(lblOnEnd);

                EndNestedIterator(nd);

                // Remove cache reference from stack
                this.helper.Emit(OpCodes.Pop);
            }

            this.iterCurr.Storage = StorageDescriptor.Local(locCache, itemStorageType, true);
        }
XmlILVisitor