internal object ChangeTypeXsltArgument(XmlQueryType xmlType, object value, Type destinationType)
{
Debug.Assert(XmlILTypeHelper.GetStorageType(xmlType).IsAssignableFrom(value.GetType()),
"Values passed to ChangeTypeXsltArgument should be in ILGen's default Clr representation.");
Debug.Assert(destinationType == XsltConvert.ObjectType || !destinationType.IsAssignableFrom(value.GetType()),
$"No need to call ChangeTypeXsltArgument since value is already assignable to destinationType {destinationType}");
switch (xmlType.TypeCode)
{
case XmlTypeCode.String:
if (destinationType == XsltConvert.DateTimeType)
{
value = XsltConvert.ToDateTime((string)value);
}
break;
case XmlTypeCode.Double:
if (destinationType != XsltConvert.DoubleType)
{
value = Convert.ChangeType(value, destinationType, CultureInfo.InvariantCulture);
}
break;
case XmlTypeCode.Node:
Debug.Assert(xmlType != XmlQueryTypeFactory.Node && xmlType != XmlQueryTypeFactory.NodeS,
"Rtf values should have been eliminated by caller.");
if (destinationType == XsltConvert.XPathNodeIteratorType)
{
value = new XPathArrayIterator((IList)value);
}
else if (destinationType == XsltConvert.XPathNavigatorArrayType)
{
// Copy sequence to XPathNavigator[]
IList <XPathNavigator> seq = (IList <XPathNavigator>)value;
XPathNavigator[] navArray = new XPathNavigator[seq.Count];
for (int i = 0; i < seq.Count; i++)
{
navArray[i] = seq[i];
}
value = navArray;
}
break;
case XmlTypeCode.Item:
{
// Only typeof(object) is supported as a destination type
if (destinationType != XsltConvert.ObjectType)
{
throw new XslTransformException(SR.Xslt_UnsupportedClrType, destinationType.Name);
}
// Convert to default, backwards-compatible representation
// 1. NodeSet: System.Xml.XPath.XPathNodeIterator
// 2. Rtf: System.Xml.XPath.XPathNavigator
// 3. Other: Default V1 representation
IList <XPathItem> seq = (IList <XPathItem>)value;
if (seq.Count == 1)
{
XPathItem item = seq[0];
if (item.IsNode)
{
// Node or Rtf
RtfNavigator rtf = item as RtfNavigator;
if (rtf != null)
{
value = rtf.ToNavigator();
}
else
{
value = new XPathArrayIterator((IList)value);
}
}
else
{
// Atomic value
value = item.TypedValue;
}
}
else
{
// Nodeset
value = new XPathArrayIterator((IList)value);
}
break;
}
}
Debug.Assert(destinationType.IsAssignableFrom(value.GetType()), $"ChangeType from type {value.GetType().Name} to type {destinationType.Name} failed");
return(value);
}