internal XPathVariableInfo(string name, XPathSequenceType type) { this._Name = name; this._Type = type; }
static Type GetReturnType(XPathSequenceType returnTypeInfo) { switch (returnTypeInfo.Cardinality) { default: case XPathSequenceCardinality.One: if (returnTypeInfo.ItemType.KindIsNode) { return typeof(XPathNavigator); } return typeof(object); case XPathSequenceCardinality.ZeroOrOne: case XPathSequenceCardinality.ZeroOrMore: return typeof(object); case XPathSequenceCardinality.OneOrMore: return typeof(XPathNavigator[]); } }
static CodeExpression GetReturnExpression(XPathSequenceType sequenceType, CodeVariableReferenceExpression varExpr) { if (sequenceType.ClrType == typeof(void)) { return new CodePropertyReferenceExpression { PropertyName = "EmptyIterator", TargetObject = new CodeTypeReferenceExpression(typeof(ExtensionObjectConvert)) }; } string convertMethod = "ToInput"; if (sequenceType.ItemType.KindIsNode) { convertMethod += "Node"; } if (sequenceType.Cardinality == XPathSequenceCardinality.ZeroOrMore || sequenceType.Cardinality == XPathSequenceCardinality.ZeroOrOne) { convertMethod += "OrEmpty"; } CodeExpression returnExpr = new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = convertMethod, TargetObject = new CodeTypeReferenceExpression(typeof(ExtensionObjectConvert)) }, Parameters = { varExpr } }; if (sequenceType.ItemType.Kind == XPathItemKind.Element || sequenceType.ItemType.Kind == XPathItemKind.SchemaElement) { returnExpr = new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = "FirstElementOrSelf", TargetObject = new CodeTypeReferenceExpression(typeof(ExtensionObjectConvert)) }, Parameters = { returnExpr } }; } return returnExpr; }
static Type GetParameterType(XPathSequenceType paramTypeInfo) { switch (paramTypeInfo.Cardinality) { case XPathSequenceCardinality.One: if (paramTypeInfo.ItemType.Kind == XPathItemKind.AnyItem) { return typeof(object); } if (paramTypeInfo.ItemType.KindIsNode) { return typeof(XPathNavigator); } switch (Type.GetTypeCode(paramTypeInfo.ItemType.ClrType)) { default: case TypeCode.String: case TypeCode.Char: case TypeCode.Object: return typeof(string); case TypeCode.Boolean: return typeof(bool); case TypeCode.Byte: return typeof(byte); case TypeCode.DateTime: return typeof(DateTime); case TypeCode.Decimal: return typeof(decimal); case TypeCode.Double: return typeof(double); case TypeCode.Int16: return typeof(Int16); case TypeCode.Int32: return typeof(Int32); case TypeCode.Int64: return typeof(Int64); case TypeCode.SByte: return typeof(SByte); case TypeCode.Single: return typeof(Single); case TypeCode.UInt16: return typeof(UInt16); case TypeCode.UInt32: return typeof(UInt32); case TypeCode.UInt64: return typeof(UInt64); } default: return typeof(XPathNodeIterator); } }
static CodeExpression GetArgumentExpression(XPathSequenceType paramTypeInfo, Type varType, CodeVariableReferenceExpression varExpr) { var convertTypeExpr = new CodeTypeReferenceExpression(typeof(ExtensionObjectConvert)); CodeExpression argExpr = varExpr; if (paramTypeInfo.ClrType.IsAssignableFrom(varType)) { return argExpr; } MethodInfo convertMethod = typeof(ExtensionObjectConvert) .GetMethod("To" + paramTypeInfo.ClrType.Name, BindingFlags.Public | BindingFlags.Static, null, new[] { varType }, null); if (convertMethod != null) { return new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = convertMethod.Name, TargetObject = convertTypeExpr, }, Parameters = { argExpr } }; } MethodInfo convertItemMethod = typeof(ExtensionObjectConvert) .GetMethod("To" + paramTypeInfo.ItemType.ClrType.Name, BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(XPathItem) }, null); CodeExpression convertItemExpr = (convertItemMethod != null) ? new CodeMethodReferenceExpression(convertTypeExpr, convertItemMethod.Name) : null; if (paramTypeInfo.ClrTypeIsEnumerable) { CodeMethodInvokeExpression methodExpr; argExpr = methodExpr = new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = "ToEnumerable", TypeArguments = { paramTypeInfo.ItemType.ClrType }, TargetObject = convertTypeExpr }, Parameters = { argExpr } }; if (convertItemExpr != null) { methodExpr.Parameters.Add(convertItemExpr); } if (paramTypeInfo.ClrType.IsArray) { argExpr = new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = "ToArray", TypeArguments = { paramTypeInfo.ItemType.ClrType }, TargetObject = new CodeTypeReferenceExpression(typeof(Enumerable)) }, Parameters = { argExpr } }; } } else if (paramTypeInfo.ClrTypeIsNullableValueType) { CodeMethodInvokeExpression methodExpr; argExpr = methodExpr = new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = "ToNullableValueType", TypeArguments = { paramTypeInfo.ItemType.ClrType }, TargetObject = convertTypeExpr }, Parameters = { argExpr } }; if (convertItemExpr != null) { methodExpr.Parameters.Add(convertItemExpr); } } else { CodeMethodInvokeExpression methodExpr; argExpr = methodExpr = new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = "ToOutput", TypeArguments = { paramTypeInfo.ClrType }, TargetObject = convertTypeExpr }, Parameters = { argExpr } }; if (convertItemExpr != null && paramTypeInfo.ClrType == paramTypeInfo.ItemType.ClrType) { methodExpr.Parameters.Add(convertItemExpr); } } return argExpr; }
CodeExpression TransformInput(CodeVariableReferenceExpression argumentsRef, int position, XPathSequenceType sequenceType) { var codeBuilder = new StringBuilder() .Append(argumentsRef.VariableName) .AppendFormatInvariant("[{0}]", position - 1); bool isAtomic = sequenceType.ItemType.Kind == XPathItemKind.Atomic; bool isNode = sequenceType.ItemType.KindIsNode; if (isAtomic) { codeBuilder.Append(".AsAtomicValues()"); } else if (isNode) { codeBuilder.Append(".AsNodes()"); } else { codeBuilder.Append(".AsItems()"); } var itemExpr = new StringBuilder("x"); if (isAtomic) { itemExpr.Append(".Value"); QName atomicSchemaType = GetAtomicSchemaType(sequenceType.ItemType); Type expectedType = sequenceType.ItemType.ClrType; Type actualType = (atomicSchemaType.Uri == XMLSchemaNamespace) ? SaxonAtomicMapping(atomicSchemaType.LocalName) : typeof(object); string expectedTypeName = GetCSharpFullName(expectedType); if (expectedType.IsAssignableFrom(actualType)) { itemExpr.Insert(0, "({0})".FormatInvariant(expectedTypeName)); } else { if (actualType == typeof(QName) && expectedType == typeof(XmlQualifiedName)) { itemExpr.Insert(0, "(({0})".FormatInvariant(GetCSharpFullName(actualType))); itemExpr.Append(").ToXmlQualifiedName()"); } else { itemExpr.Insert(0, "({0}){1}.ChangeType(".FormatInvariant(expectedTypeName, typeof(Convert).FullName)); itemExpr.AppendFormatInvariant(", typeof({0}))", expectedTypeName); } } } else if (isNode) { itemExpr.Append(".ToXPathNavigator()"); } else { itemExpr.Append(".ToXPathItem()"); } if (itemExpr.Length > 1) { codeBuilder.Append(".Select(x => "); codeBuilder.Append(itemExpr.ToString()); codeBuilder.Append(")"); } switch (sequenceType.Cardinality) { case XPathSequenceCardinality.One: codeBuilder.Append(".Single()"); break; case XPathSequenceCardinality.ZeroOrOne: if (sequenceType.ClrTypeIsNullableValueType) { codeBuilder.Insert(0, typeof(SaxonExtensions).FullName + ".SingleOrNull("); codeBuilder.Append(")"); } else { codeBuilder.Append(".SingleOrDefault()"); } break; case XPathSequenceCardinality.OneOrMore: case XPathSequenceCardinality.ZeroOrMore: if (sequenceType.ClrType.IsArray) { codeBuilder.Append(".ToArray()"); } break; } return new CodeSnippetExpression(codeBuilder.ToString()); }
static CodeExpression TransformOutput(CodeExpression functionResultRef, XPathSequenceType sequenceType, CodeExpression processorRef) { CodeExpression itemFactoryRef = GetItemFactoryReference(processorRef); CodeExpression expr = new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = "ToXdmValue", TargetObject = new CodeTypeReferenceExpression(typeof(SaxonExtensions)) }, Parameters = { functionResultRef, itemFactoryRef } }; if (sequenceType.ItemType.Kind == XPathItemKind.Element || sequenceType.ItemType.Kind == XPathItemKind.SchemaElement) { expr = new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = "FirstElementOrSelf", TargetObject = new CodeTypeReferenceExpression(typeof(SaxonExtensions)) }, Parameters = { expr } }; } return new CodeMethodInvokeExpression { Method = new CodeMethodReferenceExpression { MethodName = "GetXdmEnumerator", TargetObject = new CodeTypeReferenceExpression(typeof(SaxonExtensions)) }, Parameters = { expr } }; }