/// <summary>
/// Each XmlQueryType has multiple legal CLR representations. Ensure that all items returned by this iterator are in
/// the Clr representation specified by "storageTypeDest".
/// </summary>
public void EnsureItemStorageType(XmlQueryType xmlType, Type storageTypeDest)
{
// If source type = destination type, then done
if (_storage.ItemStorageType == storageTypeDest)
{
goto SetStorageType;
}
Debug.Assert(_storage.ItemStorageType == typeof(XPathItem) || storageTypeDest == typeof(XPathItem),
"EnsureItemStorageType must convert to or from Item");
// If items are cached,
if (_storage.IsCached)
{
// Check for special case of IList<XPathNavigator> -> IList<XPathItem>
if (_storage.ItemStorageType == typeof(XPathNavigator))
{
EnsureStack();
_helper.Call(XmlILMethods.NavsToItems);
goto SetStorageType;
}
// Check for special case of IList<XPathItem> -> IList<XPathNavigator>
if (storageTypeDest == typeof(XPathNavigator))
{
EnsureStack();
_helper.Call(XmlILMethods.ItemsToNavs);
goto SetStorageType;
}
}
// Iterate over each item, and convert each to the destination type
EnsureStackNoCache();
// If source type is Item,
if (_storage.ItemStorageType == typeof(XPathItem))
{
// Then downcast to Navigator
if (storageTypeDest == typeof(XPathNavigator))
{
_helper.Emit(OpCodes.Castclass, typeof(XPathNavigator));
}
else
{
// Call ValueAs methods for atomic types
_helper.CallValueAs(storageTypeDest);
}
goto SetStorageType;
}
else if (_storage.ItemStorageType == typeof(XPathNavigator))
{
// No-op if converting from XPathNavigator to XPathItem
Debug.Assert(storageTypeDest == typeof(XPathItem), "Must be converting from XPathNavigator to XPathItem");
goto SetStorageType;
}
// Destination type must be item, so generate code to create an XmlAtomicValue
_helper.LoadInteger(_helper.StaticData.DeclareXmlType(xmlType));
_helper.LoadQueryRuntime();
_helper.Call(XmlILMethods.StorageMethods[_storage.ItemStorageType].ToAtomicValue);
SetStorageType:
_storage = _storage.ToStorageType(storageTypeDest);
}