static XmlILMethods() { StorageMethods = new Dictionary<Type, XmlILStorageMethods>(); StorageMethods[typeof(string)] = new XmlILStorageMethods(typeof(string)); StorageMethods[typeof(bool)] = new XmlILStorageMethods(typeof(bool)); StorageMethods[typeof(int)] = new XmlILStorageMethods(typeof(int)); StorageMethods[typeof(long)] = new XmlILStorageMethods(typeof(long)); StorageMethods[typeof(decimal)] = new XmlILStorageMethods(typeof(decimal)); StorageMethods[typeof(double)] = new XmlILStorageMethods(typeof(double)); StorageMethods[typeof(float)] = new XmlILStorageMethods(typeof(float)); StorageMethods[typeof(DateTime)] = new XmlILStorageMethods(typeof(DateTime)); StorageMethods[typeof(byte[])] = new XmlILStorageMethods(typeof(byte[])); StorageMethods[typeof(XmlQualifiedName)] = new XmlILStorageMethods(typeof(XmlQualifiedName)); StorageMethods[typeof(TimeSpan)] = new XmlILStorageMethods(typeof(TimeSpan)); StorageMethods[typeof(XPathItem)] = new XmlILStorageMethods(typeof(XPathItem)); StorageMethods[typeof(XPathNavigator)] = new XmlILStorageMethods(typeof(XPathNavigator)); }
/// <summary> /// Generate code for QilNodeType.Sum, QilNodeType.Average, QilNodeType.Minimum, and QilNodeType.Maximum. /// </summary> private QilNode CreateAggregator(QilUnary ndAgg, string aggName, XmlILStorageMethods methods, MethodInfo methAgg, MethodInfo methResult) { Label lblOnEnd = _helper.DefineLabel(); Type typAgg = methAgg.DeclaringType; LocalBuilder locAgg; // Aggregate agg; // agg.Create(); locAgg = _helper.DeclareLocal(aggName, typAgg); _helper.Emit(OpCodes.Ldloca, locAgg); _helper.Call(methods.AggCreate); // foreach (num in expr) { StartNestedIterator(ndAgg.Child, lblOnEnd); _helper.Emit(OpCodes.Ldloca, locAgg); Visit(ndAgg.Child); // agg.Aggregate(num); _iterCurr.EnsureStackNoCache(); _iterCurr.EnsureItemStorageType(ndAgg.XmlType, GetItemStorageType(ndAgg)); _helper.Call(methAgg); _helper.Emit(OpCodes.Ldloca, locAgg); // } _iterCurr.LoopToEnd(lblOnEnd); // End nested iterator EndNestedIterator(ndAgg.Child); // If aggregate might be empty sequence, then generate code to handle this possibility if (ndAgg.XmlType.MaybeEmpty) { // if (agg.IsEmpty) goto LabelNextCtxt; _helper.Call(methods.AggIsEmpty); _helper.Emit(OpCodes.Brtrue, _iterCurr.GetLabelNext()); _helper.Emit(OpCodes.Ldloca, locAgg); } // result = agg.Result; _helper.Call(methResult); _iterCurr.Storage = StorageDescriptor.Stack(GetItemStorageType(ndAgg), false); return ndAgg; }