3c6daee652
Former-commit-id: f069081cc0821095435a845c961ae61cbbc95121
619 lines
23 KiB
C#
619 lines
23 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Xml;
|
|
|
|
namespace System.Runtime.Serialization
|
|
{
|
|
internal partial class XmlFormatReaderGenerator
|
|
{
|
|
partial class CriticalHelper
|
|
{
|
|
internal XmlFormatClassReaderDelegate GenerateClassReader(ClassDataContract classContract)
|
|
{
|
|
return (XmlReaderDelegator xr, XmlObjectSerializerReadContext ctx, XmlDictionaryString [] memberNames, XmlDictionaryString [] memberNamespaces) => new XmlFormatReaderInterpreter (classContract).ReadFromXml (xr, ctx, memberNames, memberNamespaces);
|
|
}
|
|
|
|
internal XmlFormatCollectionReaderDelegate GenerateCollectionReader(CollectionDataContract collectionContract)
|
|
{
|
|
return (XmlReaderDelegator xr, XmlObjectSerializerReadContext ctx, XmlDictionaryString inm, XmlDictionaryString ins, CollectionDataContract cc) => new XmlFormatReaderInterpreter (collectionContract, false).ReadCollectionFromXml (xr, ctx, inm, ins, cc);
|
|
}
|
|
|
|
internal XmlFormatGetOnlyCollectionReaderDelegate GenerateGetOnlyCollectionReader(CollectionDataContract collectionContract)
|
|
{
|
|
return (XmlReaderDelegator xr, XmlObjectSerializerReadContext ctx, XmlDictionaryString inm, XmlDictionaryString ins, CollectionDataContract cc) => new XmlFormatReaderInterpreter (collectionContract, true).ReadGetOnlyCollectionFromXml (xr, ctx, inm, ins, cc);
|
|
}
|
|
}
|
|
}
|
|
|
|
class XmlFormatReaderInterpreter
|
|
{
|
|
public XmlFormatReaderInterpreter (ClassDataContract classContract)
|
|
{
|
|
this.classContract = classContract;
|
|
}
|
|
|
|
public XmlFormatReaderInterpreter (CollectionDataContract collectionContract, bool isGetOnly)
|
|
{
|
|
this.collectionContract = collectionContract;
|
|
this.is_get_only_collection = isGetOnly;
|
|
}
|
|
|
|
bool is_get_only_collection;
|
|
|
|
ClassDataContract classContract;
|
|
|
|
CollectionDataContract collectionContract;
|
|
|
|
object objectLocal;
|
|
Type objectType;
|
|
XmlReaderDelegator xmlReader;
|
|
XmlObjectSerializerReadContext context;
|
|
|
|
XmlDictionaryString [] memberNames = null;
|
|
XmlDictionaryString [] memberNamespaces = null;
|
|
XmlDictionaryString itemName = null;
|
|
XmlDictionaryString itemNamespace = null;
|
|
|
|
public object ReadFromXml (XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces)
|
|
{
|
|
// InitArgs()
|
|
this.xmlReader = xmlReader;
|
|
this.context = context;
|
|
this.memberNames = memberNames;
|
|
this.memberNamespaces = memberNamespaces;
|
|
|
|
//DemandSerializationFormatterPermission(classContract);
|
|
//DemandMemberAccessPermission(memberAccessFlag);
|
|
CreateObject (classContract);
|
|
|
|
context.AddNewObject (objectLocal);
|
|
InvokeOnDeserializing (classContract);
|
|
|
|
string objectId = null;
|
|
|
|
if (HasFactoryMethod (classContract))
|
|
objectId = context.GetObjectId ();
|
|
if (classContract.IsISerializable)
|
|
ReadISerializable (classContract);
|
|
else
|
|
ReadClass (classContract);
|
|
bool isFactoryType = InvokeFactoryMethod (classContract, objectId);
|
|
if (Globals.TypeOfIDeserializationCallback.IsAssignableFrom (classContract.UnderlyingType))
|
|
((IDeserializationCallback) objectLocal).OnDeserialization (null);
|
|
InvokeOnDeserialized(classContract);
|
|
if (objectId == null || !isFactoryType) {
|
|
|
|
// Do a conversion back from DateTimeOffsetAdapter to DateTimeOffset after deserialization.
|
|
// DateTimeOffsetAdapter is used here for deserialization purposes to bypass the ISerializable implementation
|
|
// on DateTimeOffset; which does not work in partial trust.
|
|
|
|
if (classContract.UnderlyingType == Globals.TypeOfDateTimeOffsetAdapter)
|
|
objectLocal = DateTimeOffsetAdapter.GetDateTimeOffset ((DateTimeOffsetAdapter) objectLocal);
|
|
// else - do we have to call CodeInterpreter.ConvertValue()? I guess not...
|
|
}
|
|
return objectLocal;
|
|
}
|
|
|
|
public object ReadCollectionFromXml (XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract)
|
|
{
|
|
#region GenerateCollectionReaderHelper
|
|
// InitArgs()
|
|
this.xmlReader = xmlReader;
|
|
this.context = context;
|
|
this.itemName = itemName;
|
|
this.itemNamespace = itemNamespace;
|
|
|
|
this.collectionContract = collectionContract;
|
|
|
|
#endregion
|
|
|
|
ReadCollection (collectionContract);
|
|
|
|
return objectLocal;
|
|
}
|
|
|
|
public void ReadGetOnlyCollectionFromXml (XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract)
|
|
{
|
|
#region GenerateCollectionReaderHelper
|
|
// InitArgs()
|
|
this.xmlReader = xmlReader;
|
|
this.context = context;
|
|
this.itemName = itemName;
|
|
this.itemNamespace = itemNamespace;
|
|
|
|
this.collectionContract = collectionContract;
|
|
|
|
#endregion
|
|
|
|
ReadGetOnlyCollection (collectionContract);
|
|
}
|
|
|
|
void CreateObject (ClassDataContract classContract)
|
|
{
|
|
Type type = objectType = classContract.UnderlyingType;
|
|
if (type.IsValueType && !classContract.IsNonAttributedType)
|
|
type = Globals.TypeOfValueType;
|
|
|
|
if (classContract.UnderlyingType == Globals.TypeOfDBNull)
|
|
objectLocal = DBNull.Value;
|
|
else if (classContract.IsNonAttributedType) {
|
|
if (type.IsValueType)
|
|
objectLocal = FormatterServices.GetUninitializedObject (type);
|
|
else
|
|
objectLocal = classContract.GetNonAttributedTypeConstructor ().Invoke (new object [0]);
|
|
}
|
|
else
|
|
objectLocal = CodeInterpreter.ConvertValue (XmlFormatReaderGenerator.UnsafeGetUninitializedObject (DataContract.GetIdForInitialization (classContract)), Globals.TypeOfObject, type);
|
|
}
|
|
|
|
void InvokeOnDeserializing (ClassDataContract classContract)
|
|
{
|
|
if (classContract.BaseContract != null)
|
|
InvokeOnDeserializing (classContract.BaseContract);
|
|
if (classContract.OnDeserializing != null)
|
|
classContract.OnDeserializing.Invoke (objectLocal, new object [] {context.GetStreamingContext ()});
|
|
}
|
|
|
|
void InvokeOnDeserialized (ClassDataContract classContract)
|
|
{
|
|
if (classContract.BaseContract != null)
|
|
InvokeOnDeserialized (classContract.BaseContract);
|
|
if (classContract.OnDeserialized != null)
|
|
classContract.OnDeserialized.Invoke (objectLocal, new object [] {context.GetStreamingContext ()});
|
|
}
|
|
|
|
bool HasFactoryMethod (ClassDataContract classContract)
|
|
{
|
|
return Globals.TypeOfIObjectReference.IsAssignableFrom (classContract.UnderlyingType);
|
|
}
|
|
|
|
bool InvokeFactoryMethod (ClassDataContract classContract, string objectId)
|
|
{
|
|
if (HasFactoryMethod (classContract)) {
|
|
objectLocal = CodeInterpreter.ConvertValue (context.GetRealObject ((IObjectReference) objectLocal, objectId), Globals.TypeOfObject, classContract.UnderlyingType);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ReadISerializable (ClassDataContract classContract)
|
|
{
|
|
ConstructorInfo ctor = classContract.GetISerializableConstructor ();
|
|
var info = context.ReadSerializationInfo (xmlReader, classContract.UnderlyingType);
|
|
ctor.Invoke (objectLocal, new object [] {info, context.GetStreamingContext ()});
|
|
}
|
|
|
|
void ReadClass (ClassDataContract classContract)
|
|
{
|
|
if (classContract.HasExtensionData) {
|
|
ExtensionDataObject extensionData = new ExtensionDataObject ();
|
|
ReadMembers (classContract, extensionData);
|
|
ClassDataContract currentContract = classContract;
|
|
while (currentContract != null) {
|
|
MethodInfo extensionDataSetMethod = currentContract.ExtensionDataSetMethod;
|
|
if (extensionDataSetMethod != null)
|
|
extensionDataSetMethod.Invoke (objectLocal, new object [] {extensionData});
|
|
currentContract = currentContract.BaseContract;
|
|
}
|
|
}
|
|
else
|
|
ReadMembers (classContract, null);
|
|
}
|
|
|
|
void ReadMembers (ClassDataContract classContract, ExtensionDataObject extensionData)
|
|
{
|
|
int memberCount = classContract.MemberNames.Length;
|
|
context.IncrementItemCount (memberCount);
|
|
|
|
int memberIndex = -1;
|
|
|
|
int firstRequiredMember;
|
|
bool[] requiredMembers = GetRequiredMembers (classContract, out firstRequiredMember);
|
|
bool hasRequiredMembers = (firstRequiredMember < memberCount);
|
|
int requiredIndex = hasRequiredMembers ? firstRequiredMember : memberCount;
|
|
|
|
while (XmlObjectSerializerReadContext.MoveToNextElement (xmlReader)) {
|
|
int idx; // used as in "switch (idx)" in the original source.
|
|
if (hasRequiredMembers)
|
|
idx = context.GetMemberIndexWithRequiredMembers (xmlReader, memberNames, memberNamespaces, memberIndex, (int) requiredIndex, extensionData);
|
|
else
|
|
idx = context.GetMemberIndex (xmlReader, memberNames, memberNamespaces, memberIndex, extensionData);
|
|
|
|
if (memberCount > 0)
|
|
ReadMembers (idx, classContract, requiredMembers, ref memberIndex, ref requiredIndex);
|
|
}
|
|
|
|
if (hasRequiredMembers)
|
|
{
|
|
if (requiredIndex < memberCount)
|
|
XmlObjectSerializerReadContext.ThrowRequiredMemberMissingException (xmlReader, memberIndex, requiredIndex, memberNames);
|
|
}
|
|
}
|
|
|
|
int ReadMembers (int index, ClassDataContract classContract, bool [] requiredMembers, ref int memberIndex, ref int requiredIndex)
|
|
{
|
|
int memberCount = (classContract.BaseContract == null) ? 0 : ReadMembers (index, classContract.BaseContract, requiredMembers,
|
|
ref memberIndex, ref requiredIndex);
|
|
|
|
if (memberCount <= index && index < memberCount + classContract.Members.Count) {
|
|
DataMember dataMember = classContract.Members [index - memberCount];
|
|
Type memberType = dataMember.MemberType;
|
|
if (dataMember.IsRequired) {
|
|
int nextRequiredIndex = index + 1;
|
|
for (; nextRequiredIndex < requiredMembers.Length; nextRequiredIndex++)
|
|
if (requiredMembers [nextRequiredIndex])
|
|
break;
|
|
requiredIndex = nextRequiredIndex;
|
|
}
|
|
|
|
if (dataMember.IsGetOnlyCollection) {
|
|
var value = CodeInterpreter.GetMember (dataMember.MemberInfo, objectLocal);
|
|
context.StoreCollectionMemberInfo (value);
|
|
ReadValue (memberType, dataMember.Name, classContract.StableName.Namespace);
|
|
} else {
|
|
var value = ReadValue (memberType, dataMember.Name, classContract.StableName.Namespace);
|
|
CodeInterpreter.SetMember (dataMember.MemberInfo, objectLocal, value);
|
|
}
|
|
memberIndex = index;
|
|
}
|
|
return memberCount + classContract.Members.Count;
|
|
}
|
|
|
|
bool[] GetRequiredMembers (ClassDataContract contract, out int firstRequiredMember)
|
|
{
|
|
int memberCount = contract.MemberNames.Length;
|
|
bool [] requiredMembers = new bool [memberCount];
|
|
GetRequiredMembers (contract, requiredMembers);
|
|
for (firstRequiredMember = 0; firstRequiredMember < memberCount; firstRequiredMember++)
|
|
if (requiredMembers [firstRequiredMember])
|
|
break;
|
|
return requiredMembers;
|
|
}
|
|
|
|
int GetRequiredMembers (ClassDataContract contract, bool[] requiredMembers)
|
|
{
|
|
int memberCount = (contract.BaseContract == null) ? 0 : GetRequiredMembers (contract.BaseContract, requiredMembers);
|
|
List<DataMember> members = contract.Members;
|
|
for (int i = 0; i < members.Count; i++, memberCount++)
|
|
requiredMembers [memberCount] = members [i].IsRequired;
|
|
return memberCount;
|
|
}
|
|
|
|
object ReadValue (Type type, string name, string ns)
|
|
{
|
|
var valueType = type;
|
|
object value = null;
|
|
bool shouldAssignNullableValue = false;
|
|
int nullables = 0;
|
|
while (type.IsGenericType && type.GetGenericTypeDefinition () == Globals.TypeOfNullable) {
|
|
nullables++;
|
|
type = type.GetGenericArguments () [0];
|
|
}
|
|
|
|
PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract (type);
|
|
if ((primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) || nullables != 0 || type.IsValueType) {
|
|
context.ReadAttributes (xmlReader);
|
|
string objectId = context.ReadIfNullOrRef (xmlReader, type, DataContract.IsTypeSerializable (type));
|
|
// Deserialize null
|
|
if (objectId == Globals.NullObjectId) {
|
|
|
|
if (nullables != 0)
|
|
value = Activator.CreateInstance (valueType);
|
|
else if (type.IsValueType)
|
|
throw new SerializationException (SR.GetString (SR.ValueTypeCannotBeNull, DataContract.GetClrTypeFullName (type)));
|
|
else
|
|
value = null;
|
|
} else if (objectId == string.Empty) {
|
|
// Deserialize value
|
|
|
|
// Compare against Globals.NewObjectId, which is set to string.Empty
|
|
|
|
objectId = context.GetObjectId ();
|
|
|
|
if (type.IsValueType) {
|
|
if (!string.IsNullOrEmpty (objectId))
|
|
throw new SerializationException (SR.GetString (SR.ValueTypeCannotHaveId, DataContract.GetClrTypeFullName(type)));
|
|
}
|
|
object innerValueRead = null;
|
|
if (nullables != 0)
|
|
shouldAssignNullableValue = true;
|
|
|
|
if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) {
|
|
value = primitiveContract.XmlFormatReaderMethod.Invoke (xmlReader, new object [0]);
|
|
if (!type.IsValueType)
|
|
context.AddNewObject (value);
|
|
}
|
|
else
|
|
value = InternalDeserialize (type, name, ns);
|
|
} else {
|
|
// Deserialize ref
|
|
if (type.IsValueType)
|
|
throw new SerializationException (SR.GetString (SR.ValueTypeCannotHaveRef, DataContract.GetClrTypeFullName (type)));
|
|
else
|
|
value = CodeInterpreter.ConvertValue (context.GetExistingObject (objectId, type, name, ns), Globals.TypeOfObject, type);
|
|
}
|
|
|
|
if (shouldAssignNullableValue) {
|
|
if (objectId != Globals.NullObjectId)
|
|
value = WrapNullableObject (type, value, valueType, nullables);
|
|
}
|
|
}
|
|
else
|
|
value = InternalDeserialize (type, name, ns);
|
|
|
|
return value;
|
|
}
|
|
|
|
object InternalDeserialize (Type type, string name, string ns)
|
|
{
|
|
Type declaredType = type.IsPointer ? Globals.TypeOfReflectionPointer : type;
|
|
var obj = context.InternalDeserialize (xmlReader, DataContract.GetId (declaredType.TypeHandle), declaredType.TypeHandle, name, ns);
|
|
|
|
if (type.IsPointer)
|
|
// wow, there is no way to convert void* to object in strongly typed way...
|
|
return XmlFormatGeneratorStatics.UnboxPointer.Invoke (null, new object [] {obj});
|
|
else
|
|
return CodeInterpreter.ConvertValue (obj, Globals.TypeOfObject, type);
|
|
}
|
|
|
|
object WrapNullableObject (Type innerType, object innerValue, Type outerType, int nullables)
|
|
{
|
|
var outerValue = innerValue;
|
|
for (int i = 1; i < nullables; i++) {
|
|
Type type = Globals.TypeOfNullable.MakeGenericType (innerType);
|
|
outerValue = Activator.CreateInstance (type, new object[] { outerValue });
|
|
innerType = type;
|
|
}
|
|
return Activator.CreateInstance (outerType, new object[] { outerValue });
|
|
}
|
|
|
|
|
|
void ReadCollection (CollectionDataContract collectionContract)
|
|
{
|
|
Type type = collectionContract.UnderlyingType;
|
|
Type itemType = collectionContract.ItemType;
|
|
bool isArray = (collectionContract.Kind == CollectionKind.Array);
|
|
|
|
ConstructorInfo constructor = collectionContract.Constructor;
|
|
|
|
if (type.IsInterface) {
|
|
switch (collectionContract.Kind) {
|
|
case CollectionKind.GenericDictionary:
|
|
type = Globals.TypeOfDictionaryGeneric.MakeGenericType (itemType.GetGenericArguments ());
|
|
constructor = type.GetConstructor (BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
|
|
break;
|
|
case CollectionKind.Dictionary:
|
|
type = Globals.TypeOfHashtable;
|
|
constructor = XmlFormatGeneratorStatics.HashtableCtor;
|
|
break;
|
|
case CollectionKind.Collection:
|
|
case CollectionKind.GenericCollection:
|
|
case CollectionKind.Enumerable:
|
|
case CollectionKind.GenericEnumerable:
|
|
case CollectionKind.List:
|
|
case CollectionKind.GenericList:
|
|
type = itemType.MakeArrayType ();
|
|
isArray = true;
|
|
break;
|
|
}
|
|
}
|
|
string itemName = collectionContract.ItemName;
|
|
string itemNs = collectionContract.StableName.Namespace;
|
|
|
|
if (!isArray) {
|
|
if (type.IsValueType)
|
|
// FIXME: this is not what the original code does.
|
|
objectLocal = FormatterServices.GetUninitializedObject (type);
|
|
else {
|
|
objectLocal = constructor.Invoke (new object [0]);
|
|
context.AddNewObject (objectLocal);
|
|
}
|
|
}
|
|
|
|
int size = context.GetArraySize ();
|
|
|
|
string objectId = context.GetObjectId ();
|
|
|
|
bool canReadPrimitiveArray = false, readResult = false;
|
|
if (isArray && TryReadPrimitiveArray (type, itemType, size, out readResult))
|
|
canReadPrimitiveArray = true;
|
|
|
|
if (!readResult) {
|
|
if (size == -1) {
|
|
|
|
object growingCollection = null;
|
|
if (isArray)
|
|
growingCollection = Array.CreateInstance (itemType, 32);
|
|
|
|
int i = 0;
|
|
// FIXME: I cannot find i++ part, but without that it won't work as expected.
|
|
for (; i < int.MaxValue; i++) {
|
|
if (IsStartElement (this.itemName, this.itemNamespace)) {
|
|
context.IncrementItemCount (1);
|
|
object value = ReadCollectionItem (collectionContract, itemType, itemName, itemNs);
|
|
if (isArray) {
|
|
MethodInfo ensureArraySizeMethod = XmlFormatGeneratorStatics.EnsureArraySizeMethod.MakeGenericMethod (itemType);
|
|
growingCollection = ensureArraySizeMethod.Invoke (null, new object [] {growingCollection, i});
|
|
((Array) growingCollection).SetValue (value, i);
|
|
} else {
|
|
StoreCollectionValue (objectLocal, itemType, value, collectionContract);
|
|
}
|
|
}
|
|
else if (IsEndElement ())
|
|
break;
|
|
else
|
|
HandleUnexpectedItemInCollection (ref i);
|
|
}
|
|
|
|
if (isArray) {
|
|
MethodInfo trimArraySizeMethod = XmlFormatGeneratorStatics.TrimArraySizeMethod.MakeGenericMethod (itemType);
|
|
objectLocal = trimArraySizeMethod.Invoke (null, new object [] {growingCollection, i});
|
|
context.AddNewObjectWithId (objectId, objectLocal);
|
|
}
|
|
} else {
|
|
context.IncrementItemCount (size);
|
|
if (isArray) {
|
|
objectLocal = Array.CreateInstance (itemType, size);
|
|
context.AddNewObject (objectLocal);
|
|
}
|
|
// FIXME: I cannot find j++ part, but without that it won't work as expected.
|
|
for (int j = 0; j < size; j++) {
|
|
if (IsStartElement (this.itemName, this.itemNamespace)) {
|
|
var itemValue = ReadCollectionItem (collectionContract, itemType, itemName, itemNs);
|
|
if (isArray)
|
|
((Array) objectLocal).SetValue (itemValue, j);
|
|
else
|
|
StoreCollectionValue (objectLocal, itemType, itemValue, collectionContract);
|
|
}
|
|
else
|
|
HandleUnexpectedItemInCollection (ref j);
|
|
}
|
|
context.CheckEndOfArray (xmlReader, size, this.itemName, this.itemNamespace);
|
|
}
|
|
}
|
|
if (canReadPrimitiveArray)
|
|
context.AddNewObjectWithId (objectId, objectLocal);
|
|
}
|
|
|
|
void ReadGetOnlyCollection (CollectionDataContract collectionContract)
|
|
{
|
|
Type type = collectionContract.UnderlyingType;
|
|
Type itemType = collectionContract.ItemType;
|
|
bool isArray = (collectionContract.Kind == CollectionKind.Array);
|
|
string itemName = collectionContract.ItemName;
|
|
string itemNs = collectionContract.StableName.Namespace;
|
|
|
|
objectLocal = context.GetCollectionMember ();
|
|
|
|
//check that items are actually going to be deserialized into the collection
|
|
if (IsStartElement (this.itemName, this.itemNamespace)) {
|
|
if (objectLocal == null)
|
|
XmlObjectSerializerReadContext.ThrowNullValueReturnedForGetOnlyCollectionException (type);
|
|
else {
|
|
int size = 0;
|
|
if (isArray)
|
|
size = ((Array) objectLocal).Length;
|
|
context.AddNewObject (objectLocal);
|
|
for (int i = 0; i < int.MaxValue;) {
|
|
if (IsStartElement (this.itemName, this.itemNamespace)) {
|
|
context.IncrementItemCount (1);
|
|
var value = ReadCollectionItem (collectionContract, itemType, itemName, itemNs);
|
|
if (isArray) {
|
|
if (size == i)
|
|
XmlObjectSerializerReadContext.ThrowArrayExceededSizeException (size, type);
|
|
else
|
|
((Array) objectLocal).SetValue (value, i);
|
|
} else {
|
|
StoreCollectionValue (objectLocal, itemType, value, collectionContract);
|
|
}
|
|
}
|
|
else if (IsEndElement())
|
|
break;
|
|
else
|
|
HandleUnexpectedItemInCollection (ref i);
|
|
}
|
|
context.CheckEndOfArray (xmlReader, size, this.itemName, this.itemNamespace);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TryReadPrimitiveArray (Type type, Type itemType, int size, out bool readResult)
|
|
{
|
|
readResult = false;
|
|
PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract (itemType);
|
|
if (primitiveContract == null)
|
|
return false;
|
|
|
|
string readArrayMethod = null;
|
|
switch (Type.GetTypeCode (itemType))
|
|
{
|
|
case TypeCode.Boolean:
|
|
readArrayMethod = "TryReadBooleanArray";
|
|
break;
|
|
case TypeCode.DateTime:
|
|
readArrayMethod = "TryReadDateTimeArray";
|
|
break;
|
|
case TypeCode.Decimal:
|
|
readArrayMethod = "TryReadDecimalArray";
|
|
break;
|
|
case TypeCode.Int32:
|
|
readArrayMethod = "TryReadInt32Array";
|
|
break;
|
|
case TypeCode.Int64:
|
|
readArrayMethod = "TryReadInt64Array";
|
|
break;
|
|
case TypeCode.Single:
|
|
readArrayMethod = "TryReadSingleArray";
|
|
break;
|
|
case TypeCode.Double:
|
|
readArrayMethod = "TryReadDoubleArray";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (readArrayMethod != null) {
|
|
var mi = typeof (XmlReaderDelegator).GetMethod (readArrayMethod, Globals.ScanAllMembers);
|
|
var args = new object [] {context, itemName, itemNamespace, size, objectLocal};
|
|
readResult = (bool) mi.Invoke (xmlReader, args);
|
|
objectLocal = args.Last ();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
object ReadCollectionItem (CollectionDataContract collectionContract, Type itemType, string itemName, string itemNs)
|
|
{
|
|
if (collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary) {
|
|
context.ResetAttributes ();
|
|
return CodeInterpreter.ConvertValue (collectionContract.ItemContract.ReadXmlValue (xmlReader, context), Globals.TypeOfObject, itemType);
|
|
}
|
|
else
|
|
return ReadValue (itemType, itemName, itemNs);
|
|
}
|
|
|
|
void StoreCollectionValue (object collection, Type valueType, object value, CollectionDataContract collectionContract)
|
|
{
|
|
if (collectionContract.Kind == CollectionKind.GenericDictionary || collectionContract.Kind == CollectionKind.Dictionary) {
|
|
ClassDataContract keyValuePairContract = DataContract.GetDataContract (valueType) as ClassDataContract;
|
|
if (keyValuePairContract == null)
|
|
Fx.Assert ("Failed to create contract for KeyValuePair type");
|
|
DataMember keyMember = keyValuePairContract.Members [0];
|
|
DataMember valueMember = keyValuePairContract.Members [1];
|
|
object pkey = CodeInterpreter.GetMember (keyMember.MemberInfo, value);
|
|
object pvalue = CodeInterpreter.GetMember (valueMember.MemberInfo, value);
|
|
|
|
collectionContract.AddMethod.Invoke (collection, new object [] {pkey, pvalue});
|
|
}
|
|
else
|
|
collectionContract.AddMethod.Invoke (collection, new object [] {value});
|
|
}
|
|
|
|
void HandleUnexpectedItemInCollection (ref int iterator)
|
|
{
|
|
if (IsStartElement ()) {
|
|
context.SkipUnknownElement (xmlReader);
|
|
iterator--;
|
|
}
|
|
else
|
|
throw XmlObjectSerializerReadContext.CreateUnexpectedStateException (XmlNodeType.Element, xmlReader);
|
|
}
|
|
|
|
bool IsStartElement(XmlDictionaryString name, XmlDictionaryString ns)
|
|
{
|
|
return xmlReader.IsStartElement (name, ns);
|
|
}
|
|
|
|
bool IsStartElement()
|
|
{
|
|
return xmlReader.IsStartElement ();
|
|
}
|
|
|
|
bool IsEndElement ()
|
|
{
|
|
return xmlReader.NodeType == XmlNodeType.EndElement;
|
|
}
|
|
}
|
|
}
|