Add project files.

This commit is contained in:
Dmitry Kolchev
2019-08-29 23:24:07 +03:00
parent cf73662a92
commit b0dc0da558
80 changed files with 37714 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections;
using System.Collections.Specialized;
#if !FEATURE_SERIALIZATION
namespace System.CodeDom
#else
namespace Compat.Runtime.Serialization
#endif
{
#if !FEATURE_SERIALIZATION
public class CodeObject
#else
internal class CodeObject
#endif
{
private IDictionary _userData = null;
public CodeObject() { }
public IDictionary UserData => _userData ?? (_userData = new ListDictionary());
}
}

View File

@@ -0,0 +1,409 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
#if !FEATURE_SERIALIZATION
namespace System.CodeDom
#else
namespace Compat.Runtime.Serialization
#endif
{
[Flags]
#if !FEATURE_SERIALIZATION
public enum CodeTypeReferenceOptions
#else
internal enum CodeTypeReferenceOptions
#endif
{
GlobalReference = 0x00000001,
GenericTypeParameter = 0x00000002
}
#if !FEATURE_SERIALIZATION
public class CodeTypeReference : CodeObject
#else
internal class CodeTypeReference : CodeObject
#endif
{
private string _baseType;
private readonly bool _isInterface;
private CodeTypeReferenceCollection _typeArguments;
private bool _needsFixup = false;
public CodeTypeReference()
{
_baseType = string.Empty;
ArrayRank = 0;
ArrayElementType = null;
}
public CodeTypeReference(Type type)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (type.IsArray)
{
ArrayRank = type.GetArrayRank();
ArrayElementType = new CodeTypeReference(type.GetElementType());
_baseType = null;
}
else
{
InitializeFromType(type);
ArrayRank = 0;
ArrayElementType = null;
}
_isInterface = type.IsInterface;
}
public CodeTypeReference(Type type, CodeTypeReferenceOptions codeTypeReferenceOption) : this(type)
{
Options = codeTypeReferenceOption;
}
public CodeTypeReference(string typeName, CodeTypeReferenceOptions codeTypeReferenceOption)
{
Initialize(typeName, codeTypeReferenceOption);
}
public CodeTypeReference(string typeName)
{
Initialize(typeName);
}
private void InitializeFromType(Type type)
{
_baseType = type.Name;
if (!type.IsGenericParameter)
{
Type currentType = type;
while (currentType.IsNested)
{
currentType = currentType.DeclaringType;
_baseType = currentType.Name + "+" + _baseType;
}
if (!string.IsNullOrEmpty(type.Namespace))
{
_baseType = type.Namespace + "." + _baseType;
}
}
// pick up the type arguments from an instantiated generic type but not an open one
if (type.IsGenericType && !type.ContainsGenericParameters)
{
Type[] genericArgs = type.GetGenericArguments();
for (int i = 0; i < genericArgs.Length; i++)
{
TypeArguments.Add(new CodeTypeReference(genericArgs[i]));
}
}
else if (!type.IsGenericTypeDefinition)
{
// if the user handed us a non-generic type, but later
// appends generic type arguments, we'll pretend
// it's a generic type for their sake - this is good for
// them if they pass in System.Nullable class when they
// meant the System.Nullable<T> value type.
_needsFixup = true;
}
}
private void Initialize(string typeName)
{
Initialize(typeName, Options);
}
private void Initialize(string typeName, CodeTypeReferenceOptions options)
{
Options = options;
if (string.IsNullOrEmpty(typeName))
{
typeName = typeof(void).FullName;
_baseType = typeName;
ArrayRank = 0;
ArrayElementType = null;
return;
}
typeName = RipOffAssemblyInformationFromTypeName(typeName);
int end = typeName.Length - 1;
int current = end;
_needsFixup = true; // default to true, and if we find arity or generic type args, we'll clear the flag.
// Scan the entire string for valid array tails and store ranks for array tails
// we found in a queue.
var q = new Queue<int>();
while (current >= 0)
{
int rank = 1;
if (typeName[current--] == ']')
{
while (current >= 0 && typeName[current] == ',')
{
rank++;
current--;
}
if (current >= 0 && typeName[current] == '[')
{
// found a valid array tail
q.Enqueue(rank);
current--;
end = current;
continue;
}
}
break;
}
// Try find generic type arguments
current = end;
var typeArgumentList = new List<CodeTypeReference>();
var subTypeNames = new Stack<string>();
if (current > 0 && typeName[current--] == ']')
{
_needsFixup = false;
int unmatchedRightBrackets = 1;
int subTypeNameEndIndex = end;
// Try find the matching '[', if we can't find it, we will not try to parse the string
while (current >= 0)
{
if (typeName[current] == '[')
{
// break if we found matched brackets
if (--unmatchedRightBrackets == 0) break;
}
else if (typeName[current] == ']')
{
++unmatchedRightBrackets;
}
else if (typeName[current] == ',' && unmatchedRightBrackets == 1)
{
//
// Type name can contain nested generic types. Following is an example:
// System.Collections.Generic.Dictionary`2[[System.string, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],
// [System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]],
// mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
//
// Spliltting by ',' won't work. We need to do first-level split by ','.
//
if (current + 1 < subTypeNameEndIndex)
{
subTypeNames.Push(typeName.Substring(current + 1, subTypeNameEndIndex - current - 1));
}
subTypeNameEndIndex = current;
}
--current;
}
if (current > 0 && (end - current - 1) > 0)
{
// push the last generic type argument name if there is any
if (current + 1 < subTypeNameEndIndex)
{
subTypeNames.Push(typeName.Substring(current + 1, subTypeNameEndIndex - current - 1));
}
// we found matched brackets and the brackets contains some characters.
while (subTypeNames.Count > 0)
{
string name = RipOffAssemblyInformationFromTypeName(subTypeNames.Pop());
typeArgumentList.Add(new CodeTypeReference(name));
}
end = current - 1;
}
}
if (end < 0)
{
// this can happen if we have some string like "[...]"
_baseType = typeName;
return;
}
if (q.Count > 0)
{
CodeTypeReference type = new CodeTypeReference(typeName.Substring(0, end + 1), Options);
for (int i = 0; i < typeArgumentList.Count; i++)
{
type.TypeArguments.Add(typeArgumentList[i]);
}
while (q.Count > 1)
{
type = new CodeTypeReference(type, q.Dequeue());
}
// we don't need to create a new CodeTypeReference for the last one.
Debug.Assert(q.Count == 1, "We should have one and only one in the rank queue.");
_baseType = null;
ArrayRank = q.Dequeue();
ArrayElementType = type;
}
else if (typeArgumentList.Count > 0)
{
for (int i = 0; i < typeArgumentList.Count; i++)
{
TypeArguments.Add(typeArgumentList[i]);
}
_baseType = typeName.Substring(0, end + 1);
}
else
{
_baseType = typeName;
}
// Now see if we have some arity. baseType could be null if this is an array type.
if (_baseType != null && _baseType.IndexOf('`') != -1) // string.Contains(char) is .NetCore2.1+ specific
{
_needsFixup = false;
}
}
public CodeTypeReference(string typeName, params CodeTypeReference[] typeArguments) : this(typeName)
{
if (typeArguments != null && typeArguments.Length > 0)
{
TypeArguments.AddRange(typeArguments);
}
}
#if !FEATURE_SERIALIZATION
public CodeTypeReference(CodeTypeParameter typeParameter) :
this(typeParameter?.Name)
{
Options = CodeTypeReferenceOptions.GenericTypeParameter;
}
#endif
public CodeTypeReference(string baseType, int rank)
{
_baseType = null;
ArrayRank = rank;
ArrayElementType = new CodeTypeReference(baseType);
}
public CodeTypeReference(CodeTypeReference arrayType, int rank)
{
_baseType = null;
ArrayRank = rank;
ArrayElementType = arrayType;
}
public CodeTypeReference ArrayElementType { get; set; }
public int ArrayRank { get; set; }
internal int NestedArrayDepth => ArrayElementType == null ? 0 : 1 + ArrayElementType.NestedArrayDepth;
public string BaseType
{
get
{
if (ArrayRank > 0 && ArrayElementType != null)
{
return ArrayElementType.BaseType;
}
if (string.IsNullOrEmpty(_baseType))
{
return string.Empty;
}
string returnType = _baseType;
return _needsFixup && TypeArguments.Count > 0 ?
returnType + '`' + TypeArguments.Count.ToString(CultureInfo.InvariantCulture) :
returnType;
}
set
{
_baseType = value;
Initialize(_baseType);
}
}
public CodeTypeReferenceOptions Options { get; set; }
public CodeTypeReferenceCollection TypeArguments
{
get
{
if (ArrayRank > 0 && ArrayElementType != null)
{
return ArrayElementType.TypeArguments;
}
if (_typeArguments == null)
{
_typeArguments = new CodeTypeReferenceCollection();
}
return _typeArguments;
}
}
internal bool IsInterface => _isInterface; // Note that this only works correctly if the Type ctor was used. Otherwise, it's always false.
//
// The string for generic type argument might contain assembly information and square bracket pair.
// There might be leading spaces in front the type name.
// Following function will rip off assembly information and brackets
// Following is an example:
// " [System.Collections.Generic.List[[System.string, mscorlib, Version=2.0.0.0, Culture=neutral,
// PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]"
//
private string RipOffAssemblyInformationFromTypeName(string typeName)
{
int start = 0;
int end = typeName.Length - 1;
string result = typeName;
// skip whitespace in the beginning
while (start < typeName.Length && char.IsWhiteSpace(typeName[start])) start++;
while (end >= 0 && char.IsWhiteSpace(typeName[end])) end--;
if (start < end)
{
if (typeName[start] == '[' && typeName[end] == ']')
{
start++;
end--;
}
// if we still have a ] at the end, there's no assembly info.
if (typeName[end] != ']')
{
int commaCount = 0;
for (int index = end; index >= start; index--)
{
if (typeName[index] == ',')
{
commaCount++;
if (commaCount == 4)
{
result = typeName.Substring(start, index - start);
break;
}
}
}
}
}
return result;
}
}
}

View File

@@ -0,0 +1,80 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections;
#if !FEATURE_SERIALIZATION
namespace System.CodeDom
#else
namespace Compat.Runtime.Serialization
#endif
{
#if !FEATURE_SERIALIZATION
public class CodeTypeReferenceCollection : CollectionBase
#else
internal class CodeTypeReferenceCollection : CollectionBase
#endif
{
public CodeTypeReferenceCollection() { }
public CodeTypeReferenceCollection(CodeTypeReferenceCollection value)
{
AddRange(value);
}
public CodeTypeReferenceCollection(CodeTypeReference[] value)
{
AddRange(value);
}
public CodeTypeReference this[int index]
{
get { return ((CodeTypeReference)(List[index])); }
set { List[index] = value; }
}
public int Add(CodeTypeReference value) => List.Add(value);
public void Add(string value) => Add(new CodeTypeReference(value));
public void Add(Type value) => Add(new CodeTypeReference(value));
public void AddRange(CodeTypeReference[] value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
for (int i = 0; i < value.Length; i++)
{
Add(value[i]);
}
}
public void AddRange(CodeTypeReferenceCollection value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
int currentCount = value.Count;
for (int i = 0; i < currentCount; i++)
{
Add(value[i]);
}
}
public bool Contains(CodeTypeReference value) => List.Contains(value);
public void CopyTo(CodeTypeReference[] array, int index) => List.CopyTo(array, index);
public int IndexOf(CodeTypeReference value) => List.IndexOf(value);
public void Insert(int index, CodeTypeReference value) => List.Insert(index, value);
public void Remove(CodeTypeReference value) => List.Remove(value);
}
}

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<RootNamespace />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>TRACE;FEATURE_SERIALIZATION</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\SR.resx">
<CustomToolNamespace>Compat</CustomToolNamespace>
<Generator></Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,43 @@
using System;
using System.Diagnostics;
namespace Compat
{
internal class Fx
{
public static void Assert(string message)
{
Debug.Assert(false, message);
}
public static void Assert(bool condition, string message)
{
Debug.Assert(condition, message);
}
public static bool IsFatal(Exception ex)
{
ex = Unwrap(ex);
return ex is NullReferenceException ||
ex is StackOverflowException ||
ex is OutOfMemoryException ||
ex is System.Threading.ThreadAbortException ||
ex is System.Runtime.InteropServices.SEHException ||
ex is System.Security.SecurityException;
}
internal static Exception Unwrap(Exception ex)
{
// for certain types of exceptions, we care more about the inner
// exception
while (ex.InnerException != null &&
(ex is System.Reflection.TargetInvocationException))
{
ex = ex.InnerException;
}
return ex;
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Runtime.Serialization;
namespace Compat.Runtime
{
[Serializable]
internal class FatalException : SystemException
{
public FatalException()
{
}
public FatalException(string message) : base(message)
{
}
public FatalException(string message, Exception innerException) : base(message, innerException)
{
// This can't throw something like ArgumentException because that would be worse than
// throwing the fatal exception that was requested.
Fx.Assert(innerException == null || !Fx.IsFatal(innerException), "FatalException can't be used to wrap fatal exceptions.");
}
protected FatalException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}

View File

@@ -0,0 +1,115 @@
namespace Compat.Runtime
{
internal static class HashHelper
{
// "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm"
// DO NOT USE FOR SECURITY PURPOSES.
public static byte[] ComputeHash(byte[] buffer)
{
int[] shifts = new int[] { 7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21 };
uint[] sines = new uint[] {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };
int blocks = (buffer.Length + 8) / 64 + 1;
uint aa = 0x67452301;
uint bb = 0xefcdab89;
uint cc = 0x98badcfe;
uint dd = 0x10325476;
for (int i = 0; i < blocks; i++)
{
byte[] block = buffer;
int offset = i * 64;
if (offset + 64 > buffer.Length)
{
block = new byte[64];
for (int j = offset; j < buffer.Length; j++)
{
block[j - offset] = buffer[j];
}
if (offset <= buffer.Length)
{
block[buffer.Length - offset] = 0x80;
}
if (i == blocks - 1)
{
block[56] = (byte)(buffer.Length << 3);
block[57] = (byte)(buffer.Length >> 5);
block[58] = (byte)(buffer.Length >> 13);
block[59] = (byte)(buffer.Length >> 21);
}
offset = 0;
}
uint a = aa;
uint b = bb;
uint c = cc;
uint d = dd;
uint f;
int g;
for (int j = 0; j < 64; j++)
{
if (j < 16)
{
f = b & c | ~b & d;
g = j;
}
else if (j < 32)
{
f = b & d | c & ~d;
g = 5 * j + 1;
}
else if (j < 48)
{
f = b ^ c ^ d;
g = 3 * j + 5;
}
else
{
f = c ^ (b | ~d);
g = 7 * j;
}
g = (g & 0x0f) * 4 + offset;
uint hold = d;
d = c;
c = b;
b = a + f + sines[j] + (uint)(block[g] + (block[g + 1] << 8) + (block[g + 2] << 16) + (block[g + 3] << 24));
b = b << shifts[j & 3 | j >> 2 & ~3] | b >> 32 - shifts[j & 3 | j >> 2 & ~3];
b += c;
a = hold;
}
aa += a;
bb += b;
cc += c;
dd += d;
}
return new byte[] {
(byte)aa, (byte)(aa >> 8), (byte)(aa >> 16), (byte)(aa >> 24),
(byte)bb, (byte)(bb >> 8), (byte)(bb >> 16), (byte)(bb >> 24),
(byte)cc, (byte)(cc >> 8), (byte)(cc >> 16), (byte)(cc >> 24),
(byte)dd, (byte)(dd >> 8), (byte)(dd >> 16), (byte)(dd >> 24) };
}
}
}

View File

@@ -0,0 +1,161 @@
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal class Attributes
{
private static readonly XmlDictionaryString[] serializationLocalNames;
private static readonly XmlDictionaryString[] schemaInstanceLocalNames;
static Attributes()
{
serializationLocalNames = new XmlDictionaryString[]
{
DictionaryGlobals.IdLocalName,
DictionaryGlobals.ArraySizeLocalName,
DictionaryGlobals.RefLocalName,
DictionaryGlobals.ClrTypeLocalName,
DictionaryGlobals.ClrAssemblyLocalName,
DictionaryGlobals.ISerializableFactoryTypeLocalName
};
schemaInstanceLocalNames = new XmlDictionaryString[]
{
DictionaryGlobals.XsiNilLocalName,
DictionaryGlobals.XsiTypeLocalName
};
}
internal string Id;
internal string Ref;
internal string XsiTypeName;
internal string XsiTypeNamespace;
internal string XsiTypePrefix;
internal bool XsiNil;
internal string ClrAssembly;
internal string ClrType;
internal int ArraySZSize;
internal string FactoryTypeName;
internal string FactoryTypeNamespace;
internal string FactoryTypePrefix;
internal bool UnrecognizedAttributesFound;
internal void Read(XmlReaderDelegator reader)
{
Reset();
while (reader.MoveToNextAttribute())
{
switch (reader.IndexOfLocalName(serializationLocalNames, DictionaryGlobals.SerializationNamespace))
{
case 0:
ReadId(reader);
break;
case 1:
ReadArraySize(reader);
break;
case 2:
ReadRef(reader);
break;
case 3:
ClrType = reader.Value;
break;
case 4:
ClrAssembly = reader.Value;
break;
case 5:
ReadFactoryType(reader);
break;
default:
switch (reader.IndexOfLocalName(schemaInstanceLocalNames, DictionaryGlobals.SchemaInstanceNamespace))
{
case 0:
ReadXsiNil(reader);
break;
case 1:
ReadXsiType(reader);
break;
default:
if (!reader.IsNamespaceUri(DictionaryGlobals.XmlnsNamespace))
{
UnrecognizedAttributesFound = true;
}
break;
}
break;
}
}
reader.MoveToElement();
}
internal void Reset()
{
Id = Globals.NewObjectId;
Ref = Globals.NewObjectId;
XsiTypeName = null;
XsiTypeNamespace = null;
XsiTypePrefix = null;
XsiNil = false;
ClrAssembly = null;
ClrType = null;
ArraySZSize = -1;
FactoryTypeName = null;
FactoryTypeNamespace = null;
FactoryTypePrefix = null;
UnrecognizedAttributesFound = false;
}
private void ReadId(XmlReaderDelegator reader)
{
Id = reader.ReadContentAsString();
if (string.IsNullOrEmpty(Id))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.InvalidXsIdDefinition, Id)));
}
}
private void ReadRef(XmlReaderDelegator reader)
{
Ref = reader.ReadContentAsString();
if (string.IsNullOrEmpty(Ref))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.InvalidXsRefDefinition, Ref)));
}
}
private void ReadXsiNil(XmlReaderDelegator reader)
{
XsiNil = reader.ReadContentAsBoolean();
}
private void ReadArraySize(XmlReaderDelegator reader)
{
ArraySZSize = reader.ReadContentAsInt();
if (ArraySZSize < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.InvalidSizeDefinition, ArraySZSize)));
}
}
private void ReadXsiType(XmlReaderDelegator reader)
{
string xsiTypeString = reader.Value;
if (xsiTypeString != null && xsiTypeString.Length > 0)
{
XmlObjectSerializerReadContext.ParseQualifiedName(xsiTypeString, reader, out XsiTypeName, out XsiTypeNamespace, out XsiTypePrefix);
}
}
private void ReadFactoryType(XmlReaderDelegator reader)
{
string factoryTypeString = reader.Value;
if (factoryTypeString != null && factoryTypeString.Length > 0)
{
XmlObjectSerializerReadContext.ParseQualifiedName(factoryTypeString, reader, out FactoryTypeName, out FactoryTypeNamespace, out FactoryTypePrefix);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
namespace Compat.Runtime.Serialization
{
internal class ClassDataNode : DataNode<object>
{
private IList<ExtensionDataMember> _members;
internal ClassDataNode()
{
dataType = Globals.TypeOfClassDataNode;
}
internal IList<ExtensionDataMember> Members
{
get => _members;
set => _members = value;
}
public override void Clear()
{
base.Clear();
_members = null;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Globalization;
namespace Compat.Runtime.Serialization
{
internal class CollectionDataNode : DataNode<Array>
{
private IList<IDataNode> items;
private string itemName;
private string itemNamespace;
private int size = -1;
internal CollectionDataNode()
{
dataType = Globals.TypeOfCollectionDataNode;
}
internal IList<IDataNode> Items
{
get => items;
set => items = value;
}
internal string ItemName
{
get => itemName;
set => itemName = value;
}
internal string ItemNamespace
{
get => itemNamespace;
set => itemNamespace = value;
}
internal int Size
{
get => size;
set => size = value;
}
public override void GetData(ElementData element)
{
base.GetData(element);
element.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.ArraySizeLocalName, Size.ToString(NumberFormatInfo.InvariantInfo));
}
public override void Clear()
{
base.Clear();
items = null;
size = -1;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
namespace Compat.Runtime.Serialization
{
internal class DataContractPairKey
{
private readonly object _object1;
private readonly object _object2;
public DataContractPairKey(object object1, object object2)
{
_object1 = object1;
_object2 = object2;
}
public override bool Equals(object other)
{
DataContractPairKey otherKey = other as DataContractPairKey;
if (otherKey == null)
{
return false;
}
return ((otherKey._object1 == _object1 && otherKey._object2 == _object2) || (otherKey._object1 == _object2 && otherKey._object2 == _object1));
}
public override int GetHashCode()
{
return _object1.GetHashCode() ^ _object2.GetHashCode();
}
}
}

View File

@@ -0,0 +1,522 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Xml;
using DataContractResolver = System.Runtime.Serialization.DataContractResolver;
namespace Compat.Runtime.Serialization
{
using DataContractDictionary = Dictionary<XmlQualifiedName, DataContract>;
internal sealed class DataContractSerializer : XmlObjectSerializer
{
private Type _rootType;
private DataContract rootContract; // post-surrogate
private bool needsContractNsAtRoot;
private XmlDictionaryString rootName;
private XmlDictionaryString rootNamespace;
private int maxItemsInObjectGraph;
private bool ignoreExtensionDataObject;
private bool preserveObjectReferences;
private IDataContractSurrogate dataContractSurrogate;
private ReadOnlyCollection<Type> knownTypeCollection;
internal IList<Type> knownTypeList;
internal DataContractDictionary knownDataContracts;
private DataContractResolver dataContractResolver;
private bool serializeReadOnlyTypes;
public DataContractSerializer(Type type)
: this(type, (IEnumerable<Type>)null)
{
}
public DataContractSerializer(Type type, IEnumerable<Type> knownTypes)
: this(type, knownTypes, int.MaxValue, false, false, null)
{
}
public DataContractSerializer(Type type,
IEnumerable<Type> knownTypes,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate)
: this(type, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, null)
{
}
public DataContractSerializer(Type type,
IEnumerable<Type> knownTypes,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate,
DataContractResolver dataContractResolver)
{
Initialize(type, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, dataContractResolver, false);
}
public DataContractSerializer(Type type, string rootName, string rootNamespace)
: this(type, rootName, rootNamespace, null)
{
}
public DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerable<Type> knownTypes)
: this(type, rootName, rootNamespace, knownTypes, int.MaxValue, false, false, null)
{
}
public DataContractSerializer(Type type, string rootName, string rootNamespace,
IEnumerable<Type> knownTypes,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate)
: this(type, rootName, rootNamespace, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, null)
{
}
public DataContractSerializer(Type type, string rootName, string rootNamespace,
IEnumerable<Type> knownTypes,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate,
DataContractResolver dataContractResolver)
{
XmlDictionary dictionary = new XmlDictionary(2);
Initialize(type, dictionary.Add(rootName), dictionary.Add(DataContract.GetNamespace(rootNamespace)), knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, dataContractResolver, false);
}
public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace)
: this(type, rootName, rootNamespace, null)
{
}
public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace, IEnumerable<Type> knownTypes)
: this(type, rootName, rootNamespace, knownTypes, int.MaxValue, false, false, null, null)
{
}
public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
IEnumerable<Type> knownTypes,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate)
: this(type, rootName, rootNamespace, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, null)
{
}
public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
IEnumerable<Type> knownTypes,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate,
DataContractResolver dataContractResolver)
{
Initialize(type, rootName, rootNamespace, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, dataContractResolver, false);
}
public DataContractSerializer(Type type, DataContractSerializerSettings settings)
{
if (settings == null)
{
settings = new DataContractSerializerSettings();
}
Initialize(type, settings.RootName, settings.RootNamespace, settings.KnownTypes, settings.MaxItemsInObjectGraph, settings.IgnoreExtensionDataObject,
settings.PreserveObjectReferences, settings.DataContractSurrogate, settings.DataContractResolver, settings.SerializeReadOnlyTypes);
}
private void Initialize(
Type type,
IEnumerable<Type> knownTypes,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate,
DataContractResolver dataContractResolver,
bool serializeReadOnlyTypes)
{
_rootType = type ?? throw new ArgumentNullException(nameof(type));
if (knownTypes != null)
{
knownTypeList = new List<Type>();
foreach (Type knownType in knownTypes)
{
knownTypeList.Add(knownType);
}
}
if (maxItemsInObjectGraph < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxItemsInObjectGraph), SR.ValueMustBeNonNegative));
}
this.maxItemsInObjectGraph = maxItemsInObjectGraph;
this.ignoreExtensionDataObject = ignoreExtensionDataObject;
this.preserveObjectReferences = preserveObjectReferences;
this.dataContractSurrogate = dataContractSurrogate;
this.dataContractResolver = dataContractResolver;
this.serializeReadOnlyTypes = serializeReadOnlyTypes;
}
private void Initialize(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
IEnumerable<Type> knownTypes,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate,
DataContractResolver dataContractResolver,
bool serializeReadOnlyTypes)
{
Initialize(type, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, dataContractResolver, serializeReadOnlyTypes);
// validate root name and namespace are both non-null
this.rootName = rootName;
this.rootNamespace = rootNamespace;
}
public ReadOnlyCollection<Type> KnownTypes
{
get
{
if (knownTypeCollection == null)
{
if (knownTypeList != null)
{
knownTypeCollection = new ReadOnlyCollection<Type>(knownTypeList);
}
else
{
knownTypeCollection = new ReadOnlyCollection<Type>(Globals.EmptyTypeArray);
}
}
return knownTypeCollection;
}
}
internal override DataContractDictionary KnownDataContracts
{
get
{
if (knownDataContracts == null && knownTypeList != null)
{
// This assignment may be performed concurrently and thus is a race condition.
// It's safe, however, because at worse a new (and identical) dictionary of
// data contracts will be created and re-assigned to this field. Introduction
// of a lock here could lead to deadlocks.
knownDataContracts = XmlObjectSerializerContext.GetDataContractsForKnownTypes(knownTypeList);
}
return knownDataContracts;
}
}
public int MaxItemsInObjectGraph => maxItemsInObjectGraph;
public IDataContractSurrogate DataContractSurrogate => dataContractSurrogate;
public bool PreserveObjectReferences => preserveObjectReferences;
public bool IgnoreExtensionDataObject => ignoreExtensionDataObject;
public DataContractResolver DataContractResolver => dataContractResolver;
public bool SerializeReadOnlyTypes => serializeReadOnlyTypes;
private DataContract RootContract
{
get
{
if (rootContract == null)
{
rootContract = DataContract.GetDataContract(((dataContractSurrogate == null) ? _rootType : GetSurrogatedType(dataContractSurrogate, _rootType)));
needsContractNsAtRoot = CheckIfNeedsContractNsAtRoot(rootName, rootNamespace, rootContract);
}
return rootContract;
}
}
internal override void InternalWriteObject(XmlWriterDelegator writer, object graph)
{
InternalWriteObject(writer, graph, null);
}
internal override void InternalWriteObject(XmlWriterDelegator writer, object graph, DataContractResolver dataContractResolver)
{
InternalWriteStartObject(writer, graph);
InternalWriteObjectContent(writer, graph, dataContractResolver);
InternalWriteEndObject(writer);
}
public override void WriteObject(XmlWriter writer, object graph)
{
WriteObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
}
public override void WriteStartObject(XmlWriter writer, object graph)
{
WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
}
public override void WriteObjectContent(XmlWriter writer, object graph)
{
WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
}
public override void WriteEndObject(XmlWriter writer)
{
WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
}
public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
{
WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
}
public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
{
WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
}
public override void WriteEndObject(XmlDictionaryWriter writer)
{
WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
}
public void WriteObject(XmlDictionaryWriter writer, object graph, DataContractResolver dataContractResolver)
{
WriteObjectHandleExceptions(new XmlWriterDelegator(writer), graph, dataContractResolver);
}
public override object ReadObject(XmlReader reader)
{
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), true /*verifyObjectName*/);
}
public override object ReadObject(XmlReader reader, bool verifyObjectName)
{
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
}
public override bool IsStartObject(XmlReader reader)
{
return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
}
public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
{
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
}
public override bool IsStartObject(XmlDictionaryReader reader)
{
return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
}
public object ReadObject(XmlDictionaryReader reader, bool verifyObjectName, DataContractResolver dataContractResolver)
{
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName, dataContractResolver);
}
internal override void InternalWriteStartObject(XmlWriterDelegator writer, object graph)
{
WriteRootElement(writer, RootContract, rootName, rootNamespace, needsContractNsAtRoot);
}
internal override void InternalWriteObjectContent(XmlWriterDelegator writer, object graph)
{
InternalWriteObjectContent(writer, graph, null);
}
internal void InternalWriteObjectContent(XmlWriterDelegator writer, object graph, DataContractResolver dataContractResolver)
{
if (MaxItemsInObjectGraph == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
}
DataContract contract = RootContract;
Type declaredType = contract.UnderlyingType;
Type graphType = (graph == null) ? declaredType : graph.GetType();
if (dataContractSurrogate != null)
{
graph = SurrogateToDataContractType(dataContractSurrogate, graph, declaredType, ref graphType);
}
if (dataContractResolver == null)
{
dataContractResolver = DataContractResolver;
}
if (graph == null)
{
if (IsRootXmlAny(rootName, contract))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.IsAnyCannotBeNull, declaredType)));
}
WriteNull(writer);
}
else
{
if (declaredType == graphType)
{
if (contract.CanContainReferences)
{
XmlObjectSerializerWriteContext context = XmlObjectSerializerWriteContext.CreateContext(this, contract, dataContractResolver);
context.HandleGraphAtTopLevel(writer, graph, contract);
context.SerializeWithoutXsiType(contract, writer, graph, declaredType.TypeHandle);
}
else
{
contract.WriteXmlValue(writer, graph, null);
}
}
else
{
XmlObjectSerializerWriteContext context = null;
if (IsRootXmlAny(rootName, contract))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.IsAnyCannotBeSerializedAsDerivedType, graphType, contract.UnderlyingType)));
}
contract = GetDataContract(contract, declaredType, graphType);
context = XmlObjectSerializerWriteContext.CreateContext(this, RootContract, dataContractResolver);
if (contract.CanContainReferences)
{
context.HandleGraphAtTopLevel(writer, graph, contract);
}
context.OnHandleIsReference(writer, contract, graph);
context.SerializeWithXsiTypeAtTopLevel(contract, writer, graph, declaredType.TypeHandle, graphType);
}
}
}
internal static DataContract GetDataContract(DataContract declaredTypeContract, Type declaredType, Type objectType)
{
if (declaredType.IsInterface && CollectionDataContract.IsCollectionInterface(declaredType))
{
return declaredTypeContract;
}
else if (declaredType.IsArray)//Array covariance is not supported in XSD
{
return declaredTypeContract;
}
else
{
return DataContract.GetDataContract(objectType.TypeHandle, objectType, SerializationMode.SharedContract);
}
}
internal void SetDataContractSurrogate(IDataContractSurrogate adapter)
{
dataContractSurrogate = adapter;
}
internal override void InternalWriteEndObject(XmlWriterDelegator writer)
{
if (!IsRootXmlAny(rootName, RootContract))
{
writer.WriteEndElement();
}
}
internal override object InternalReadObject(XmlReaderDelegator xmlReader, bool verifyObjectName)
{
return InternalReadObject(xmlReader, verifyObjectName, null);
}
internal override object InternalReadObject(XmlReaderDelegator xmlReader, bool verifyObjectName, DataContractResolver dataContractResolver)
{
if (MaxItemsInObjectGraph == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
}
if (dataContractResolver == null)
{
dataContractResolver = DataContractResolver;
}
if (verifyObjectName)
{
if (!InternalIsStartObject(xmlReader))
{
XmlDictionaryString expectedName;
XmlDictionaryString expectedNs;
if (rootName == null)
{
expectedName = RootContract.TopLevelElementName;
expectedNs = RootContract.TopLevelElementNamespace;
}
else
{
expectedName = rootName;
expectedNs = rootNamespace;
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationExceptionWithReaderDetails(SR.Format(SR.ExpectingElement, expectedNs, expectedName), xmlReader));
}
}
else if (!IsStartElement(xmlReader))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationExceptionWithReaderDetails(SR.Format(SR.ExpectingElementAtDeserialize, XmlNodeType.Element), xmlReader));
}
DataContract contract = RootContract;
if (contract.IsPrimitive && object.ReferenceEquals(contract.UnderlyingType, _rootType) /*handle Nullable<T> differently*/)
{
return contract.ReadXmlValue(xmlReader, null);
}
if (IsRootXmlAny(rootName, contract))
{
return XmlObjectSerializerReadContext.ReadRootIXmlSerializable(xmlReader, contract as XmlDataContract, false /*isMemberType*/);
}
XmlObjectSerializerReadContext context = XmlObjectSerializerReadContext.CreateContext(this, contract, dataContractResolver);
return context.InternalDeserialize(xmlReader, _rootType, contract, null, null);
}
internal override bool InternalIsStartObject(XmlReaderDelegator reader)
{
return IsRootElement(reader, RootContract, rootName, rootNamespace);
}
internal override Type GetSerializeType(object graph)
{
return (graph == null) ? _rootType : graph.GetType();
}
internal override Type GetDeserializeType()
{
return _rootType;
}
internal static object SurrogateToDataContractType(IDataContractSurrogate dataContractSurrogate, object oldObj, Type surrogatedDeclaredType, ref Type objType)
{
object obj = DataContractSurrogateCaller.GetObjectToSerialize(dataContractSurrogate, oldObj, objType, surrogatedDeclaredType);
if (obj != oldObj)
{
if (obj == null)
{
objType = Globals.TypeOfObject;
}
else
{
objType = obj.GetType();
}
}
return obj;
}
internal static Type GetSurrogatedType(IDataContractSurrogate dataContractSurrogate, Type type)
{
return DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, DataContract.UnwrapNullableType(type));
}
}
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Xml;
using DataContractResolver = System.Runtime.Serialization.DataContractResolver;
namespace Compat.Runtime.Serialization
{
public class DataContractSerializerSettings
{
/// <summary>
/// Gets or sets Dummy documentation
/// </summary>
public XmlDictionaryString RootName { get; set; }
/// <summary>
/// Gets or sets Dummy documentation
/// </summary>
public XmlDictionaryString RootNamespace { get; set; }
/// <summary>
/// Gets or sets Dummy documentation
/// </summary>
public IEnumerable<Type> KnownTypes { get; set; }
/// <summary>
/// Gets or sets Dummy documentation
/// </summary>
public int MaxItemsInObjectGraph { get; set; } = int.MaxValue;
/// <summary>
/// Gets or sets a value indicating whether Dummy documentation
/// </summary>
public bool IgnoreExtensionDataObject { get; set; }
/// <summary>
/// Gets or sets a value indicating whether Dummy documentation
/// </summary>
public bool PreserveObjectReferences { get; set; }
/// <summary>
/// Gets or sets Dummy documentation
/// </summary>
internal IDataContractSurrogate DataContractSurrogate { get; set; }
/// <summary>
/// Gets or sets Dummy documentation
/// </summary>
public DataContractResolver DataContractResolver { get; set; }
/// <summary>
/// Gets or sets a value indicating whether Dummy documentation
/// </summary>
public bool SerializeReadOnlyTypes { get; set; }
}
}

View File

@@ -0,0 +1,548 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using InvalidDataContractException = System.Runtime.Serialization.InvalidDataContractException;
namespace Compat.Runtime.Serialization
{
using DataContractDictionary = Dictionary<XmlQualifiedName, DataContract>;
internal class DataContractSet
{
private Dictionary<XmlQualifiedName, DataContract> contracts;
private Dictionary<DataContract, object> processedContracts;
private readonly IDataContractSurrogate dataContractSurrogate;
private Hashtable surrogateDataTable;
private DataContractDictionary knownTypesForObject;
private readonly ICollection<Type> referencedTypes;
private readonly ICollection<Type> referencedCollectionTypes;
private Dictionary<XmlQualifiedName, object> referencedTypesDictionary;
private Dictionary<XmlQualifiedName, object> referencedCollectionTypesDictionary;
internal DataContractSet(IDataContractSurrogate dataContractSurrogate) : this(dataContractSurrogate, null, null) { }
internal DataContractSet(IDataContractSurrogate dataContractSurrogate, ICollection<Type> referencedTypes, ICollection<Type> referencedCollectionTypes)
{
this.dataContractSurrogate = dataContractSurrogate;
this.referencedTypes = referencedTypes;
this.referencedCollectionTypes = referencedCollectionTypes;
}
internal DataContractSet(DataContractSet dataContractSet)
{
if (dataContractSet == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("dataContractSet"));
}
dataContractSurrogate = dataContractSet.dataContractSurrogate;
referencedTypes = dataContractSet.referencedTypes;
referencedCollectionTypes = dataContractSet.referencedCollectionTypes;
foreach (KeyValuePair<XmlQualifiedName, DataContract> pair in dataContractSet)
{
Add(pair.Key, pair.Value);
}
if (dataContractSet.processedContracts != null)
{
foreach (KeyValuePair<DataContract, object> pair in dataContractSet.processedContracts)
{
ProcessedContracts.Add(pair.Key, pair.Value);
}
}
}
private Dictionary<XmlQualifiedName, DataContract> Contracts
{
get
{
if (contracts == null)
{
contracts = new Dictionary<XmlQualifiedName, DataContract>();
}
return contracts;
}
}
private Dictionary<DataContract, object> ProcessedContracts
{
get
{
if (processedContracts == null)
{
processedContracts = new Dictionary<DataContract, object>();
}
return processedContracts;
}
}
private Hashtable SurrogateDataTable
{
get
{
if (surrogateDataTable == null)
{
surrogateDataTable = new Hashtable();
}
return surrogateDataTable;
}
}
internal DataContractDictionary KnownTypesForObject
{
get => knownTypesForObject;
set => knownTypesForObject = value;
}
internal void Add(Type type)
{
DataContract dataContract = GetDataContract(type);
EnsureTypeNotGeneric(dataContract.UnderlyingType);
Add(dataContract);
}
internal static void EnsureTypeNotGeneric(Type type)
{
if (type.ContainsGenericParameters)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.GenericTypeNotExportable, type)));
}
}
private void Add(DataContract dataContract)
{
Add(dataContract.StableName, dataContract);
}
public void Add(XmlQualifiedName name, DataContract dataContract)
{
if (dataContract.IsBuiltInDataContract)
{
return;
}
InternalAdd(name, dataContract);
}
internal void InternalAdd(XmlQualifiedName name, DataContract dataContract)
{
if (Contracts.TryGetValue(name, out DataContract dataContractInSet))
{
if (!dataContractInSet.Equals(dataContract))
{
if (dataContract.UnderlyingType == null || dataContractInSet.UnderlyingType == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.DupContractInDataContractSet, dataContract.StableName.Name, dataContract.StableName.Namespace)));
}
else
{
bool typeNamesEqual = (DataContract.GetClrTypeFullName(dataContract.UnderlyingType) == DataContract.GetClrTypeFullName(dataContractInSet.UnderlyingType));
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.DupTypeContractInDataContractSet, (typeNamesEqual ? dataContract.UnderlyingType.AssemblyQualifiedName : DataContract.GetClrTypeFullName(dataContract.UnderlyingType)), (typeNamesEqual ? dataContractInSet.UnderlyingType.AssemblyQualifiedName : DataContract.GetClrTypeFullName(dataContractInSet.UnderlyingType)), dataContract.StableName.Name, dataContract.StableName.Namespace)));
}
}
}
else
{
Contracts.Add(name, dataContract);
if (dataContract is ClassDataContract)
{
AddClassDataContract((ClassDataContract)dataContract);
}
else if (dataContract is CollectionDataContract)
{
AddCollectionDataContract((CollectionDataContract)dataContract);
}
else if (dataContract is XmlDataContract)
{
AddXmlDataContract((XmlDataContract)dataContract);
}
}
}
private void AddClassDataContract(ClassDataContract classDataContract)
{
if (classDataContract.BaseContract != null)
{
Add(classDataContract.BaseContract.StableName, classDataContract.BaseContract);
}
if (!classDataContract.IsISerializable)
{
if (classDataContract.Members != null)
{
for (int i = 0; i < classDataContract.Members.Count; i++)
{
DataMember dataMember = classDataContract.Members[i];
DataContract memberDataContract = GetMemberTypeDataContract(dataMember);
if (dataContractSurrogate != null && dataMember.MemberInfo != null)
{
object customData = DataContractSurrogateCaller.GetCustomDataToExport(
dataContractSurrogate,
dataMember.MemberInfo,
memberDataContract.UnderlyingType);
if (customData != null)
{
SurrogateDataTable.Add(dataMember, customData);
}
}
Add(memberDataContract.StableName, memberDataContract);
}
}
}
AddKnownDataContracts(classDataContract.KnownDataContracts);
}
private void AddCollectionDataContract(CollectionDataContract collectionDataContract)
{
if (collectionDataContract.IsDictionary)
{
ClassDataContract keyValueContract = collectionDataContract.ItemContract as ClassDataContract;
AddClassDataContract(keyValueContract);
}
else
{
DataContract itemContract = GetItemTypeDataContract(collectionDataContract);
if (itemContract != null)
{
Add(itemContract.StableName, itemContract);
}
}
AddKnownDataContracts(collectionDataContract.KnownDataContracts);
}
private void AddXmlDataContract(XmlDataContract xmlDataContract)
{
AddKnownDataContracts(xmlDataContract.KnownDataContracts);
}
private void AddKnownDataContracts(DataContractDictionary knownDataContracts)
{
if (knownDataContracts != null)
{
foreach (DataContract knownDataContract in knownDataContracts.Values)
{
Add(knownDataContract);
}
}
}
internal XmlQualifiedName GetStableName(Type clrType)
{
if (dataContractSurrogate != null)
{
Type dcType = DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, clrType);
return DataContract.GetStableName(dcType);
}
return DataContract.GetStableName(clrType);
}
internal DataContract GetDataContract(Type clrType)
{
if (dataContractSurrogate == null)
{
return DataContract.GetDataContract(clrType);
}
DataContract dataContract = DataContract.GetBuiltInDataContract(clrType);
if (dataContract != null)
{
return dataContract;
}
Type dcType = DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, clrType);
dataContract = DataContract.GetDataContract(dcType);
if (!SurrogateDataTable.Contains(dataContract))
{
object customData = DataContractSurrogateCaller.GetCustomDataToExport(
dataContractSurrogate, clrType, dcType);
if (customData != null)
{
SurrogateDataTable.Add(dataContract, customData);
}
}
return dataContract;
}
internal DataContract GetMemberTypeDataContract(DataMember dataMember)
{
if (dataMember.MemberInfo != null)
{
Type dataMemberType = dataMember.MemberType;
if (dataMember.IsGetOnlyCollection)
{
if (dataContractSurrogate != null)
{
Type dcType = DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, dataMemberType);
if (dcType != dataMemberType)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupported,
DataContract.GetClrTypeFullName(dataMemberType), DataContract.GetClrTypeFullName(dataMember.MemberInfo.DeclaringType), dataMember.MemberInfo.Name)));
}
}
return DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(dataMemberType.TypeHandle), dataMemberType.TypeHandle, dataMemberType, SerializationMode.SharedContract);
}
else
{
return GetDataContract(dataMemberType);
}
}
return dataMember.MemberTypeContract;
}
internal DataContract GetItemTypeDataContract(CollectionDataContract collectionContract)
{
if (collectionContract.ItemType != null)
{
return GetDataContract(collectionContract.ItemType);
}
return collectionContract.ItemContract;
}
internal object GetSurrogateData(object key)
{
return SurrogateDataTable[key];
}
internal void SetSurrogateData(object key, object surrogateData)
{
SurrogateDataTable[key] = surrogateData;
}
public DataContract this[XmlQualifiedName key]
{
get
{
DataContract dataContract = DataContract.GetBuiltInDataContract(key.Name, key.Namespace);
if (dataContract == null)
{
Contracts.TryGetValue(key, out dataContract);
}
return dataContract;
}
}
public IDataContractSurrogate DataContractSurrogate => dataContractSurrogate;
public bool Remove(XmlQualifiedName key)
{
if (DataContract.GetBuiltInDataContract(key.Name, key.Namespace) != null)
{
return false;
}
return Contracts.Remove(key);
}
public IEnumerator<KeyValuePair<XmlQualifiedName, DataContract>> GetEnumerator()
{
return Contracts.GetEnumerator();
}
internal bool IsContractProcessed(DataContract dataContract)
{
return ProcessedContracts.ContainsKey(dataContract);
}
internal void SetContractProcessed(DataContract dataContract)
{
ProcessedContracts.Add(dataContract, dataContract);
}
private Dictionary<XmlQualifiedName, object> GetReferencedTypes()
{
if (referencedTypesDictionary == null)
{
referencedTypesDictionary = new Dictionary<XmlQualifiedName, object>
{
//Always include Nullable as referenced type
//Do not allow surrogating Nullable<T>
{ DataContract.GetStableName(Globals.TypeOfNullable), Globals.TypeOfNullable }
};
if (referencedTypes != null)
{
foreach (Type type in referencedTypes)
{
if (type == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.ReferencedTypesCannotContainNull));
}
AddReferencedType(referencedTypesDictionary, type);
}
}
}
return referencedTypesDictionary;
}
private Dictionary<XmlQualifiedName, object> GetReferencedCollectionTypes()
{
if (referencedCollectionTypesDictionary == null)
{
referencedCollectionTypesDictionary = new Dictionary<XmlQualifiedName, object>();
if (referencedCollectionTypes != null)
{
foreach (Type type in referencedCollectionTypes)
{
if (type == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.ReferencedCollectionTypesCannotContainNull));
}
AddReferencedType(referencedCollectionTypesDictionary, type);
}
}
XmlQualifiedName genericDictionaryName = DataContract.GetStableName(Globals.TypeOfDictionaryGeneric);
if (!referencedCollectionTypesDictionary.ContainsKey(genericDictionaryName) && GetReferencedTypes().ContainsKey(genericDictionaryName))
{
AddReferencedType(referencedCollectionTypesDictionary, Globals.TypeOfDictionaryGeneric);
}
}
return referencedCollectionTypesDictionary;
}
private void AddReferencedType(Dictionary<XmlQualifiedName, object> referencedTypes, Type type)
{
if (IsTypeReferenceable(type))
{
XmlQualifiedName stableName;
try
{
stableName = GetStableName(type);
}
catch (InvalidDataContractException)
{
// Type not referenceable if we can't get a stable name.
return;
}
catch (InvalidOperationException)
{
// Type not referenceable if we can't get a stable name.
return;
}
if (referencedTypes.TryGetValue(stableName, out object value))
{
Type referencedType = value as Type;
if (referencedType != null)
{
if (referencedType != type)
{
referencedTypes.Remove(stableName);
List<Type> types = new List<Type>
{
referencedType,
type
};
referencedTypes.Add(stableName, types);
}
}
else
{
List<Type> types = (List<Type>)value;
if (!types.Contains(type))
{
types.Add(type);
}
}
}
else
{
referencedTypes.Add(stableName, type);
}
}
}
internal bool TryGetReferencedType(XmlQualifiedName stableName, DataContract dataContract, out Type type)
{
return TryGetReferencedType(stableName, dataContract, false/*useReferencedCollectionTypes*/, out type);
}
internal bool TryGetReferencedCollectionType(XmlQualifiedName stableName, DataContract dataContract, out Type type)
{
return TryGetReferencedType(stableName, dataContract, true/*useReferencedCollectionTypes*/, out type);
}
private bool TryGetReferencedType(XmlQualifiedName stableName, DataContract dataContract, bool useReferencedCollectionTypes, out Type type)
{
Dictionary<XmlQualifiedName, object> referencedTypes = useReferencedCollectionTypes ? GetReferencedCollectionTypes() : GetReferencedTypes();
if (referencedTypes.TryGetValue(stableName, out object value))
{
type = value as Type;
if (type != null)
{
return true;
}
else
{
// Throw ambiguous type match exception
List<Type> types = (List<Type>)value;
StringBuilder errorMessage = new StringBuilder();
bool containsGenericType = false;
for (int i = 0; i < types.Count; i++)
{
Type conflictingType = types[i];
if (!containsGenericType)
{
containsGenericType = conflictingType.IsGenericTypeDefinition;
}
errorMessage.AppendFormat("{0}\"{1}\" ", Environment.NewLine, conflictingType.AssemblyQualifiedName);
if (dataContract != null)
{
DataContract other = GetDataContract(conflictingType);
errorMessage.Append(SR.Format(((other != null && other.Equals(dataContract)) ? SR.ReferencedTypeMatchingMessage : SR.ReferencedTypeNotMatchingMessage)));
}
}
if (containsGenericType)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(
(useReferencedCollectionTypes ? SR.AmbiguousReferencedCollectionTypes1 : SR.AmbiguousReferencedTypes1),
errorMessage.ToString())));
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(
(useReferencedCollectionTypes ? SR.AmbiguousReferencedCollectionTypes3 : SR.AmbiguousReferencedTypes3),
XmlConvert.DecodeName(stableName.Name),
stableName.Namespace,
errorMessage.ToString())));
}
}
}
type = null;
return false;
}
private static bool IsTypeReferenceable(Type type)
{
try
{
return (type.IsSerializable ||
type.IsDefined(Globals.TypeOfDataContractAttribute, false) ||
(Globals.TypeOfIXmlSerializable.IsAssignableFrom(type) && !type.IsGenericTypeDefinition) ||
CollectionDataContract.IsCollection(type, out Type itemType) ||
ClassDataContract.IsNonAttributedTypeValidForSerialization(type));
}
catch (Exception ex)
{
// An exception can be thrown in the designer when a project has a runtime binding redirection for a referenced assembly or a reference dependent assembly.
// Type.IsDefined is known to throw System.IO.FileLoadException.
// ClassDataContract.IsNonAttributedTypeValidForSerialization is known to throw System.IO.FileNotFoundException.
// We guard against all non-critical exceptions.
if (Fx.IsFatal(ex))
{
throw;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.ObjectModel;
using System.Reflection;
namespace Compat.Runtime.Serialization
{
internal static class DataContractSurrogateCaller
{
internal static Type GetDataContractType(IDataContractSurrogate surrogate, Type type)
{
if (DataContract.GetBuiltInDataContract(type) != null)
{
return type;
}
Type dcType = surrogate.GetDataContractType(type);
if (dcType == null)
{
return type;
}
return dcType;
}
internal static object GetObjectToSerialize(IDataContractSurrogate surrogate, object obj, Type objType, Type membertype)
{
if (obj == null)
{
return null;
}
if (DataContract.GetBuiltInDataContract(objType) != null)
{
return obj;
}
return surrogate.GetObjectToSerialize(obj, membertype);
}
internal static object GetDeserializedObject(IDataContractSurrogate surrogate, object obj, Type objType, Type memberType)
{
if (obj == null)
{
return null;
}
if (DataContract.GetBuiltInDataContract(objType) != null)
{
return obj;
}
return surrogate.GetDeserializedObject(obj, memberType);
}
internal static object GetCustomDataToExport(IDataContractSurrogate surrogate, MemberInfo memberInfo, Type dataContractType)
{
return surrogate.GetCustomDataToExport(memberInfo, dataContractType);
}
internal static object GetCustomDataToExport(IDataContractSurrogate surrogate, Type clrType, Type dataContractType)
{
if (DataContract.GetBuiltInDataContract(clrType) != null)
{
return null;
}
return surrogate.GetCustomDataToExport(clrType, dataContractType);
}
internal static void GetKnownCustomDataTypes(IDataContractSurrogate surrogate, Collection<Type> customDataTypes)
{
surrogate.GetKnownCustomDataTypes(customDataTypes);
}
internal static Type GetReferencedTypeOnImport(IDataContractSurrogate surrogate, string typeName, string typeNamespace, object customData)
{
if (DataContract.GetBuiltInDataContract(typeName, typeNamespace) != null)
{
return null;
}
return surrogate.GetReferencedTypeOnImport(typeName, typeNamespace, customData);
}
}
}

View File

@@ -0,0 +1,295 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Compat.Runtime.Serialization
{
internal class DataMember
{
private readonly CriticalHelper helper;
internal DataMember()
{
helper = new CriticalHelper();
}
internal DataMember(MemberInfo memberInfo)
{
helper = new CriticalHelper(memberInfo);
}
internal DataMember(string name)
{
helper = new CriticalHelper(name);
}
internal DataMember(DataContract memberTypeContract, string name, bool isNullable, bool isRequired, bool emitDefaultValue, int order)
{
helper = new CriticalHelper(memberTypeContract, name, isNullable, isRequired, emitDefaultValue, order);
}
internal MemberInfo MemberInfo => helper.MemberInfo;
internal string Name
{
get => helper.Name;
set => helper.Name = value;
}
internal int Order
{
get => helper.Order;
set => helper.Order = value;
}
internal bool IsRequired
{
get => helper.IsRequired;
set => helper.IsRequired = value;
}
internal bool EmitDefaultValue
{
get => helper.EmitDefaultValue;
set => helper.EmitDefaultValue = value;
}
internal bool IsNullable
{
get => helper.IsNullable;
set => helper.IsNullable = value;
}
internal bool IsGetOnlyCollection
{
get => helper.IsGetOnlyCollection;
set => helper.IsGetOnlyCollection = value;
}
internal Type MemberType => helper.MemberType;
internal DataContract MemberTypeContract
{
get => helper.MemberTypeContract;
set => helper.MemberTypeContract = value;
}
internal bool HasConflictingNameAndType
{
get => helper.HasConflictingNameAndType;
set => helper.HasConflictingNameAndType = value;
}
internal DataMember ConflictingMember
{
get => helper.ConflictingMember;
set => helper.ConflictingMember = value;
}
private class CriticalHelper
{
private DataContract memberTypeContract;
private string name;
private int order;
private bool isRequired;
private bool emitDefaultValue;
private bool isNullable;
private bool isGetOnlyCollection = false;
private readonly MemberInfo memberInfo;
private bool hasConflictingNameAndType;
private DataMember conflictingMember;
internal CriticalHelper()
{
emitDefaultValue = Globals.DefaultEmitDefaultValue;
}
internal CriticalHelper(MemberInfo memberInfo)
{
emitDefaultValue = Globals.DefaultEmitDefaultValue;
this.memberInfo = memberInfo;
}
internal CriticalHelper(string name)
{
Name = name;
}
internal CriticalHelper(DataContract memberTypeContract, string name, bool isNullable, bool isRequired, bool emitDefaultValue, int order)
{
MemberTypeContract = memberTypeContract;
Name = name;
IsNullable = isNullable;
IsRequired = isRequired;
EmitDefaultValue = emitDefaultValue;
Order = order;
}
internal MemberInfo MemberInfo => memberInfo;
internal string Name
{
get => name;
set => name = value;
}
internal int Order
{
get => order;
set => order = value;
}
internal bool IsRequired
{
get => isRequired;
set => isRequired = value;
}
internal bool EmitDefaultValue
{
get => emitDefaultValue;
set => emitDefaultValue = value;
}
internal bool IsNullable
{
get => isNullable;
set => isNullable = value;
}
internal bool IsGetOnlyCollection
{
get => isGetOnlyCollection;
set => isGetOnlyCollection = value;
}
internal Type MemberType
{
get
{
FieldInfo field = MemberInfo as FieldInfo;
if (field != null)
{
return field.FieldType;
}
return ((PropertyInfo)MemberInfo).PropertyType;
}
}
internal DataContract MemberTypeContract
{
get
{
if (memberTypeContract == null)
{
if (MemberInfo != null)
{
if (IsGetOnlyCollection)
{
memberTypeContract = DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(MemberType.TypeHandle), MemberType.TypeHandle, MemberType, SerializationMode.SharedContract);
}
else
{
memberTypeContract = DataContract.GetDataContract(MemberType);
}
}
}
return memberTypeContract;
}
set => memberTypeContract = value;
}
internal bool HasConflictingNameAndType
{
get => hasConflictingNameAndType;
set => hasConflictingNameAndType = value;
}
internal DataMember ConflictingMember
{
get => conflictingMember;
set => conflictingMember = value;
}
}
internal bool RequiresMemberAccessForGet()
{
MemberInfo memberInfo = MemberInfo;
FieldInfo field = memberInfo as FieldInfo;
if (field != null)
{
return DataContract.FieldRequiresMemberAccess(field);
}
else
{
PropertyInfo property = (PropertyInfo)memberInfo;
MethodInfo getMethod = property.GetGetMethod(true /*nonPublic*/);
if (getMethod != null)
{
return DataContract.MethodRequiresMemberAccess(getMethod) || !DataContract.IsTypeVisible(property.PropertyType);
}
}
return false;
}
internal bool RequiresMemberAccessForSet()
{
MemberInfo memberInfo = MemberInfo;
FieldInfo field = memberInfo as FieldInfo;
if (field != null)
{
return DataContract.FieldRequiresMemberAccess(field);
}
else
{
PropertyInfo property = (PropertyInfo)memberInfo;
MethodInfo setMethod = property.GetSetMethod(true /*nonPublic*/);
if (setMethod != null)
{
return DataContract.MethodRequiresMemberAccess(setMethod) || !DataContract.IsTypeVisible(property.PropertyType);
}
}
return false;
}
internal DataMember BindGenericParameters(DataContract[] paramContracts, Dictionary<DataContract, DataContract> boundContracts)
{
DataContract memberTypeContract = MemberTypeContract.BindGenericParameters(paramContracts, boundContracts);
DataMember boundDataMember = new DataMember(memberTypeContract,
Name,
!memberTypeContract.IsValueType,
IsRequired,
EmitDefaultValue,
Order);
return boundDataMember;
}
internal bool Equals(object other, Dictionary<DataContractPairKey, object> checkedContracts)
{
if ((object)this == other)
{
return true;
}
DataMember dataMember = other as DataMember;
if (dataMember != null)
{
// Note: comparison does not use Order hint since it influences element order but does not specify exact order
bool thisIsNullable = (MemberTypeContract == null) ? false : !MemberTypeContract.IsValueType;
bool dataMemberIsNullable = (dataMember.MemberTypeContract == null) ? false : !dataMember.MemberTypeContract.IsValueType;
return (Name == dataMember.Name
&& (IsNullable || thisIsNullable) == (dataMember.IsNullable || dataMemberIsNullable)
&& IsRequired == dataMember.IsRequired
&& EmitDefaultValue == dataMember.EmitDefaultValue
&& MemberTypeContract.Equals(dataMember.MemberTypeContract, checkedContracts));
}
return false;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}

View File

@@ -0,0 +1,132 @@
using System;
using System.Globalization;
namespace Compat.Runtime.Serialization
{
internal class DataNode<T> : IDataNode
{
protected Type dataType;
private T _value;
private string _dataContractName;
private string _dataContractNamespace;
private string _clrTypeName;
private string _clrAssemblyName;
private string _id = Globals.NewObjectId;
private bool _isFinalValue;
internal DataNode()
{
dataType = typeof(T);
_isFinalValue = true;
}
internal DataNode(T value)
: this()
{
_value = value;
}
public Type DataType => dataType;
public object Value
{
get => _value;
set => _value = (T)value;
}
bool IDataNode.IsFinalValue
{
get => _isFinalValue;
set => _isFinalValue = value;
}
public T GetValue()
{
return _value;
}
public string DataContractName
{
get => _dataContractName;
set => _dataContractName = value;
}
public string DataContractNamespace
{
get => _dataContractNamespace;
set => _dataContractNamespace = value;
}
public string ClrTypeName
{
get => _clrTypeName;
set => _clrTypeName = value;
}
public string ClrAssemblyName
{
get => _clrAssemblyName;
set => _clrAssemblyName = value;
}
public bool PreservesReferences => (Id != Globals.NewObjectId);
public string Id
{
get => _id;
set => _id = value;
}
public virtual void GetData(ElementData element)
{
element.dataNode = this;
element.attributeCount = 0;
element.childElementIndex = 0;
if (DataContractName != null)
{
AddQualifiedNameAttribute(element, Globals.XsiPrefix, Globals.XsiTypeLocalName, Globals.SchemaInstanceNamespace, DataContractName, DataContractNamespace);
}
if (ClrTypeName != null)
{
element.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.ClrTypeLocalName, ClrTypeName);
}
if (ClrAssemblyName != null)
{
element.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.ClrAssemblyLocalName, ClrAssemblyName);
}
}
public virtual void Clear()
{
// dataContractName not cleared because it is used when re-serializing from unknown data
_clrTypeName = _clrAssemblyName = null;
}
internal void AddQualifiedNameAttribute(ElementData element, string elementPrefix, string elementName, string elementNs, string valueName, string valueNs)
{
string prefix = ExtensionDataReader.GetPrefix(valueNs);
element.AddAttribute(elementPrefix, elementNs, elementName, string.Format(CultureInfo.InvariantCulture, "{0}:{1}", prefix, valueName));
bool prefixDeclaredOnElement = false;
if (element.attributes != null)
{
for (int i = 0; i < element.attributes.Length; i++)
{
AttributeData attribute = element.attributes[i];
if (attribute != null && attribute.prefix == Globals.XmlnsPrefix && attribute.localName == prefix)
{
prefixDeclaredOnElement = true;
break;
}
}
}
if (!prefixDeclaredOnElement)
{
element.AddAttribute(Globals.XmlnsPrefix, Globals.XmlnsNamespace, prefix, valueNs);
}
}
}
}

View File

@@ -0,0 +1,70 @@
using Compat.Xml;
using System;
using System.Globalization;
using DataContractAttribute = System.Runtime.Serialization.DataContractAttribute;
using DataMemberAttribute = System.Runtime.Serialization.DataMemberAttribute;
namespace Compat.Runtime.Serialization
{
[DataContract(Name = "DateTimeOffset", Namespace = "http://schemas.datacontract.org/2004/07/System")]
internal struct DateTimeOffsetAdapter
{
private DateTime _utcDateTime;
private short _offsetMinutes;
public DateTimeOffsetAdapter(DateTime dateTime, short offsetMinutes)
{
_utcDateTime = dateTime;
_offsetMinutes = offsetMinutes;
}
[DataMember(Name = "DateTime", IsRequired = true)]
public DateTime UtcDateTime
{
get => _utcDateTime;
set => _utcDateTime = value;
}
[DataMember(Name = "OffsetMinutes", IsRequired = true)]
public short OffsetMinutes
{
get => _offsetMinutes;
set => _offsetMinutes = value;
}
public static DateTimeOffset GetDateTimeOffset(DateTimeOffsetAdapter value)
{
try
{
switch (value.UtcDateTime.Kind)
{
case DateTimeKind.Unspecified:
return new DateTimeOffset(value.UtcDateTime, new TimeSpan(0, value.OffsetMinutes, 0));
//DateTimeKind.Utc and DateTimeKind.Local
//Read in deserialized DateTime portion of the DateTimeOffsetAdapter and convert DateTimeKind to Unspecified.
//Apply ofset information read from OffsetMinutes portion of the DateTimeOffsetAdapter.
//Return converted DateTimeoffset object.
default:
DateTimeOffset deserialized = new DateTimeOffset(value.UtcDateTime);
return deserialized.ToOffset(new TimeSpan(0, value.OffsetMinutes, 0));
}
}
catch (ArgumentException exception)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTimeOffset", exception));
}
}
public static DateTimeOffsetAdapter GetDateTimeOffsetAdapter(DateTimeOffset value)
{
return new DateTimeOffsetAdapter(value.UtcDateTime, (short)value.Offset.TotalMinutes);
}
public string ToString(IFormatProvider provider)
{
return "DateTime: " + UtcDateTime + ", Offset: " + OffsetMinutes;
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Diagnostics;
namespace Compat.Runtime.Serialization
{
internal class DiagnosticUtility
{
public class ExceptionUtility
{
internal static Exception ThrowHelperFatal(string message, Exception innerException)
{
return ThrowHelperError(new FatalException(message, innerException));
}
internal static Exception ThrowHelperError(Exception exception)
{
return ThrowHelper(exception, TraceEventType.Error);
}
internal static Exception ThrowHelper(Exception exception, TraceEventType eventType)
{
return exception;
}
}
}
}

View File

@@ -0,0 +1,178 @@
using System;
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal static class DictionaryGlobals
{
public readonly static XmlDictionaryString EmptyString;
public readonly static XmlDictionaryString SchemaInstanceNamespace;
public readonly static XmlDictionaryString SchemaNamespace;
public readonly static XmlDictionaryString SerializationNamespace;
public readonly static XmlDictionaryString XmlnsNamespace;
public readonly static XmlDictionaryString XsiTypeLocalName;
public readonly static XmlDictionaryString XsiNilLocalName;
public readonly static XmlDictionaryString ClrTypeLocalName;
public readonly static XmlDictionaryString ClrAssemblyLocalName;
public readonly static XmlDictionaryString ArraySizeLocalName;
public readonly static XmlDictionaryString IdLocalName;
public readonly static XmlDictionaryString RefLocalName;
public readonly static XmlDictionaryString ISerializableFactoryTypeLocalName;
public readonly static XmlDictionaryString CharLocalName;
public readonly static XmlDictionaryString BooleanLocalName;
public readonly static XmlDictionaryString SignedByteLocalName;
public readonly static XmlDictionaryString UnsignedByteLocalName;
public readonly static XmlDictionaryString ShortLocalName;
public readonly static XmlDictionaryString UnsignedShortLocalName;
public readonly static XmlDictionaryString IntLocalName;
public readonly static XmlDictionaryString UnsignedIntLocalName;
public readonly static XmlDictionaryString LongLocalName;
public readonly static XmlDictionaryString UnsignedLongLocalName;
public readonly static XmlDictionaryString FloatLocalName;
public readonly static XmlDictionaryString DoubleLocalName;
public readonly static XmlDictionaryString DecimalLocalName;
public readonly static XmlDictionaryString DateTimeLocalName;
public readonly static XmlDictionaryString StringLocalName;
public readonly static XmlDictionaryString ByteArrayLocalName;
public readonly static XmlDictionaryString ObjectLocalName;
public readonly static XmlDictionaryString TimeSpanLocalName;
public readonly static XmlDictionaryString GuidLocalName;
public readonly static XmlDictionaryString UriLocalName;
public readonly static XmlDictionaryString QNameLocalName;
public readonly static XmlDictionaryString Space;
public readonly static XmlDictionaryString timeLocalName;
public readonly static XmlDictionaryString dateLocalName;
public readonly static XmlDictionaryString hexBinaryLocalName;
public readonly static XmlDictionaryString gYearMonthLocalName;
public readonly static XmlDictionaryString gYearLocalName;
public readonly static XmlDictionaryString gMonthDayLocalName;
public readonly static XmlDictionaryString gDayLocalName;
public readonly static XmlDictionaryString gMonthLocalName;
public readonly static XmlDictionaryString integerLocalName;
public readonly static XmlDictionaryString positiveIntegerLocalName;
public readonly static XmlDictionaryString negativeIntegerLocalName;
public readonly static XmlDictionaryString nonPositiveIntegerLocalName;
public readonly static XmlDictionaryString nonNegativeIntegerLocalName;
public readonly static XmlDictionaryString normalizedStringLocalName;
public readonly static XmlDictionaryString tokenLocalName;
public readonly static XmlDictionaryString languageLocalName;
public readonly static XmlDictionaryString NameLocalName;
public readonly static XmlDictionaryString NCNameLocalName;
public readonly static XmlDictionaryString XSDIDLocalName;
public readonly static XmlDictionaryString IDREFLocalName;
public readonly static XmlDictionaryString IDREFSLocalName;
public readonly static XmlDictionaryString ENTITYLocalName;
public readonly static XmlDictionaryString ENTITIESLocalName;
public readonly static XmlDictionaryString NMTOKENLocalName;
public readonly static XmlDictionaryString NMTOKENSLocalName;
public readonly static XmlDictionaryString AsmxTypesNamespace;
static DictionaryGlobals()
{
// Update array size when adding new strings or templates
XmlDictionary dictionary = new XmlDictionary(61);
try
{
// 0
SchemaInstanceNamespace = dictionary.Add(Globals.SchemaInstanceNamespace);
SerializationNamespace = dictionary.Add(Globals.SerializationNamespace);
SchemaNamespace = dictionary.Add(Globals.SchemaNamespace);
XsiTypeLocalName = dictionary.Add(Globals.XsiTypeLocalName);
XsiNilLocalName = dictionary.Add(Globals.XsiNilLocalName);
// 5
IdLocalName = dictionary.Add(Globals.IdLocalName);
RefLocalName = dictionary.Add(Globals.RefLocalName);
ArraySizeLocalName = dictionary.Add(Globals.ArraySizeLocalName);
EmptyString = dictionary.Add(String.Empty);
ISerializableFactoryTypeLocalName = dictionary.Add(Globals.ISerializableFactoryTypeLocalName);
// 10
XmlnsNamespace = dictionary.Add(Globals.XmlnsNamespace);
CharLocalName = dictionary.Add("char");
BooleanLocalName = dictionary.Add("boolean");
SignedByteLocalName = dictionary.Add("byte");
UnsignedByteLocalName = dictionary.Add("unsignedByte");
// 15
ShortLocalName = dictionary.Add("short");
UnsignedShortLocalName = dictionary.Add("unsignedShort");
IntLocalName = dictionary.Add("int");
UnsignedIntLocalName = dictionary.Add("unsignedInt");
LongLocalName = dictionary.Add("long");
// 20
UnsignedLongLocalName = dictionary.Add("unsignedLong");
FloatLocalName = dictionary.Add("float");
DoubleLocalName = dictionary.Add("double");
DecimalLocalName = dictionary.Add("decimal");
DateTimeLocalName = dictionary.Add("dateTime");
// 25
StringLocalName = dictionary.Add("string");
ByteArrayLocalName = dictionary.Add("base64Binary");
ObjectLocalName = dictionary.Add("anyType");
TimeSpanLocalName = dictionary.Add("duration");
GuidLocalName = dictionary.Add("guid");
// 30
UriLocalName = dictionary.Add("anyURI");
QNameLocalName = dictionary.Add("QName");
ClrTypeLocalName = dictionary.Add(Globals.ClrTypeLocalName);
ClrAssemblyLocalName = dictionary.Add(Globals.ClrAssemblyLocalName);
Space = dictionary.Add(Globals.Space);
// 35
timeLocalName = dictionary.Add("time");
dateLocalName = dictionary.Add("date");
hexBinaryLocalName = dictionary.Add("hexBinary");
gYearMonthLocalName = dictionary.Add("gYearMonth");
gYearLocalName = dictionary.Add("gYear");
// 40
gMonthDayLocalName = dictionary.Add("gMonthDay");
gDayLocalName = dictionary.Add("gDay");
gMonthLocalName = dictionary.Add("gMonth");
integerLocalName = dictionary.Add("integer");
positiveIntegerLocalName = dictionary.Add("positiveInteger");
// 45
negativeIntegerLocalName = dictionary.Add("negativeInteger");
nonPositiveIntegerLocalName = dictionary.Add("nonPositiveInteger");
nonNegativeIntegerLocalName = dictionary.Add("nonNegativeInteger");
normalizedStringLocalName = dictionary.Add("normalizedString");
tokenLocalName = dictionary.Add("token");
// 50
languageLocalName = dictionary.Add("language");
NameLocalName = dictionary.Add("Name");
NCNameLocalName = dictionary.Add("NCName");
XSDIDLocalName = dictionary.Add("ID");
IDREFLocalName = dictionary.Add("IDREF");
// 55
IDREFSLocalName = dictionary.Add("IDREFS");
ENTITYLocalName = dictionary.Add("ENTITY");
ENTITIESLocalName = dictionary.Add("ENTITIES");
NMTOKENLocalName = dictionary.Add("NMTOKEN");
NMTOKENSLocalName = dictionary.Add("NMTOKENS");
// 60
AsmxTypesNamespace = dictionary.Add("http://microsoft.com/wsdl/types/");
// Add new templates here
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
}
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
namespace Compat.Runtime.Serialization
{
internal class AttributeData
{
public string prefix;
public string ns;
public string localName;
public string value;
}
internal class ElementData
{
public string localName;
public string ns;
public string prefix;
public int attributeCount;
public AttributeData[] attributes;
public IDataNode dataNode;
public int childElementIndex;
public void AddAttribute(string prefix, string ns, string name, string value)
{
GrowAttributesIfNeeded();
AttributeData attribute = attributes[attributeCount];
if (attribute == null)
{
attributes[attributeCount] = attribute = new AttributeData();
}
attribute.prefix = prefix;
attribute.ns = ns;
attribute.localName = name;
attribute.value = value;
attributeCount++;
}
private void GrowAttributesIfNeeded()
{
if (attributes == null)
{
attributes = new AttributeData[4];
}
else if (attributes.Length == attributeCount)
{
AttributeData[] newAttributes = new AttributeData[attributes.Length * 2];
Array.Copy(attributes, 0, newAttributes, 0, attributes.Length);
attributes = newAttributes;
}
}
}
}

View File

@@ -0,0 +1,508 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Security;
using System.Threading;
using System.Xml;
using DataContractAttribute = System.Runtime.Serialization.DataContractAttribute;
using EnumMemberAttribute = System.Runtime.Serialization.EnumMemberAttribute;
namespace Compat.Runtime.Serialization
{
internal sealed class EnumDataContract : DataContract
{
private readonly EnumDataContractCriticalHelper helper;
internal EnumDataContract()
: base(new EnumDataContractCriticalHelper())
{
helper = base.Helper as EnumDataContractCriticalHelper;
}
internal EnumDataContract(Type type)
: base(new EnumDataContractCriticalHelper(type))
{
helper = base.Helper as EnumDataContractCriticalHelper;
}
internal static XmlQualifiedName GetBaseContractName(Type type)
{
return EnumDataContractCriticalHelper.GetBaseContractName(type);
}
internal static Type GetBaseType(XmlQualifiedName baseContractName)
{
return EnumDataContractCriticalHelper.GetBaseType(baseContractName);
}
internal XmlQualifiedName BaseContractName
{
get => helper.BaseContractName;
set => helper.BaseContractName = value;
}
internal List<DataMember> Members
{
get => helper.Members;
set => helper.Members = value;
}
internal List<long> Values
{
get => helper.Values;
set => helper.Values = value;
}
internal bool IsFlags
{
get => helper.IsFlags;
set => helper.IsFlags = value;
}
internal bool IsULong
{
get => helper.IsULong;
}
private XmlDictionaryString[] ChildElementNames
{
get => helper.ChildElementNames;
}
internal override bool CanContainReferences => false;
private class EnumDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
private static readonly Dictionary<Type, XmlQualifiedName> typeToName;
private static readonly Dictionary<XmlQualifiedName, Type> nameToType;
private XmlQualifiedName baseContractName;
private List<DataMember> members;
private List<long> values;
private bool isULong;
private bool isFlags;
private readonly bool hasDataContract;
private readonly XmlDictionaryString[] childElementNames;
static EnumDataContractCriticalHelper()
{
typeToName = new Dictionary<Type, XmlQualifiedName>();
nameToType = new Dictionary<XmlQualifiedName, Type>();
Add(typeof(sbyte), "byte");
Add(typeof(byte), "unsignedByte");
Add(typeof(short), "short");
Add(typeof(ushort), "unsignedShort");
Add(typeof(int), "int");
Add(typeof(uint), "unsignedInt");
Add(typeof(long), "long");
Add(typeof(ulong), "unsignedLong");
}
internal static void Add(Type type, string localName)
{
XmlQualifiedName stableName = CreateQualifiedName(localName, Globals.SchemaNamespace);
typeToName.Add(type, stableName);
nameToType.Add(stableName, type);
}
internal static XmlQualifiedName GetBaseContractName(Type type)
{
typeToName.TryGetValue(type, out XmlQualifiedName retVal);
return retVal;
}
internal static Type GetBaseType(XmlQualifiedName baseContractName)
{
nameToType.TryGetValue(baseContractName, out Type retVal);
return retVal;
}
internal EnumDataContractCriticalHelper()
{
IsValueType = true;
}
internal EnumDataContractCriticalHelper(Type type)
: base(type)
{
StableName = DataContract.GetStableName(type, out hasDataContract);
Type baseType = Enum.GetUnderlyingType(type);
baseContractName = GetBaseContractName(baseType);
ImportBaseType(baseType);
IsFlags = type.IsDefined(Globals.TypeOfFlagsAttribute, false);
ImportDataMembers();
XmlDictionary dictionary = new XmlDictionary(2 + Members.Count);
Name = dictionary.Add(StableName.Name);
Namespace = dictionary.Add(StableName.Namespace);
childElementNames = new XmlDictionaryString[Members.Count];
for (int i = 0; i < Members.Count; i++)
{
childElementNames[i] = dictionary.Add(Members[i].Name);
}
if (TryGetDCAttribute(type, out DataContractAttribute dataContractAttribute))
{
if (dataContractAttribute.IsReference)
{
DataContract.ThrowInvalidDataContractException(
SR.Format(SR.EnumTypeCannotHaveIsReference,
DataContract.GetClrTypeFullName(type),
dataContractAttribute.IsReference,
false),
type);
}
}
}
internal XmlQualifiedName BaseContractName
{
get => baseContractName;
set
{
baseContractName = value;
Type baseType = GetBaseType(baseContractName);
if (baseType == null)
{
ThrowInvalidDataContractException(SR.Format(SR.InvalidEnumBaseType, value.Name, value.Namespace, StableName.Name, StableName.Namespace));
}
ImportBaseType(baseType);
}
}
internal List<DataMember> Members
{
get => members;
set => members = value;
}
internal List<long> Values
{
get => values;
set => values = value;
}
internal bool IsFlags
{
get => isFlags;
set => isFlags = value;
}
internal bool IsULong => isULong;
internal XmlDictionaryString[] ChildElementNames => childElementNames;
private void ImportBaseType(Type baseType)
{
isULong = (baseType == Globals.TypeOfULong);
}
private void ImportDataMembers()
{
Type type = UnderlyingType;
FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public);
Dictionary<string, DataMember> memberValuesTable = new Dictionary<string, DataMember>();
List<DataMember> tempMembers = new List<DataMember>(fields.Length);
List<long> tempValues = new List<long>(fields.Length);
for (int i = 0; i < fields.Length; i++)
{
FieldInfo field = fields[i];
bool enumMemberValid = false;
if (hasDataContract)
{
object[] memberAttributes = field.GetCustomAttributes(Globals.TypeOfEnumMemberAttribute, false);
if (memberAttributes != null && memberAttributes.Length > 0)
{
if (memberAttributes.Length > 1)
{
ThrowInvalidDataContractException(SR.Format(SR.TooManyEnumMembers, DataContract.GetClrTypeFullName(field.DeclaringType), field.Name));
}
EnumMemberAttribute memberAttribute = (EnumMemberAttribute)memberAttributes[0];
DataMember memberContract = new DataMember(field);
if (memberAttribute.IsValueSetExplicitly)
{
if (memberAttribute.Value == null || memberAttribute.Value.Length == 0)
{
ThrowInvalidDataContractException(SR.Format(SR.InvalidEnumMemberValue, field.Name, DataContract.GetClrTypeFullName(type)));
}
memberContract.Name = memberAttribute.Value;
}
else
{
memberContract.Name = field.Name;
}
ClassDataContract.CheckAndAddMember(tempMembers, memberContract, memberValuesTable);
enumMemberValid = true;
}
object[] dataMemberAttributes = field.GetCustomAttributes(Globals.TypeOfDataMemberAttribute, false);
if (dataMemberAttributes != null && dataMemberAttributes.Length > 0)
{
ThrowInvalidDataContractException(SR.Format(SR.DataMemberOnEnumField, DataContract.GetClrTypeFullName(field.DeclaringType), field.Name));
}
}
else
{
if (!field.IsNotSerialized)
{
DataMember memberContract = new DataMember(field)
{
Name = field.Name
};
ClassDataContract.CheckAndAddMember(tempMembers, memberContract, memberValuesTable);
enumMemberValid = true;
}
}
if (enumMemberValid)
{
object enumValue = field.GetValue(null);
if (isULong)
{
tempValues.Add((long)((IConvertible)enumValue).ToUInt64(null));
}
else
{
tempValues.Add(((IConvertible)enumValue).ToInt64(null));
}
}
}
Thread.MemoryBarrier();
members = tempMembers;
values = tempValues;
}
}
internal void WriteEnumValue(XmlWriterDelegator writer, object value)
{
long longValue = IsULong ? (long)((IConvertible)value).ToUInt64(null) : ((IConvertible)value).ToInt64(null);
for (int i = 0; i < Values.Count; i++)
{
if (longValue == Values[i])
{
writer.WriteString(ChildElementNames[i].Value);
return;
}
}
if (IsFlags)
{
int zeroIndex = -1;
bool noneWritten = true;
for (int i = 0; i < Values.Count; i++)
{
long current = Values[i];
if (current == 0)
{
zeroIndex = i;
continue;
}
if (longValue == 0)
{
break;
}
if ((current & longValue) == current)
{
if (noneWritten)
{
noneWritten = false;
}
else
{
writer.WriteString(DictionaryGlobals.Space.Value);
}
writer.WriteString(ChildElementNames[i].Value);
longValue &= ~current;
}
}
// enforce that enum value was completely parsed
if (longValue != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.InvalidEnumValueOnWrite, value, DataContract.GetClrTypeFullName(UnderlyingType))));
}
if (noneWritten && zeroIndex >= 0)
{
writer.WriteString(ChildElementNames[zeroIndex].Value);
}
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.InvalidEnumValueOnWrite, value, DataContract.GetClrTypeFullName(UnderlyingType))));
}
}
internal object ReadEnumValue(XmlReaderDelegator reader)
{
string stringValue = reader.ReadElementContentAsString();
long longValue = 0;
int i = 0;
if (IsFlags)
{
// Skip initial spaces
for (; i < stringValue.Length; i++)
{
if (stringValue[i] != ' ')
{
break;
}
}
// Read space-delimited values
int startIndex = i;
int count = 0;
for (; i < stringValue.Length; i++)
{
if (stringValue[i] == ' ')
{
count = i - startIndex;
if (count > 0)
{
longValue |= ReadEnumValue(stringValue, startIndex, count);
}
for (++i; i < stringValue.Length; i++)
{
if (stringValue[i] != ' ')
{
break;
}
}
startIndex = i;
if (i == stringValue.Length)
{
break;
}
}
}
count = i - startIndex;
if (count > 0)
{
longValue |= ReadEnumValue(stringValue, startIndex, count);
}
}
else
{
if (stringValue.Length == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.InvalidEnumValueOnRead, stringValue, DataContract.GetClrTypeFullName(UnderlyingType))));
}
longValue = ReadEnumValue(stringValue, 0, stringValue.Length);
}
if (IsULong)
{
return Enum.ToObject(UnderlyingType, (ulong)longValue);
}
return Enum.ToObject(UnderlyingType, longValue);
}
private long ReadEnumValue(string value, int index, int count)
{
for (int i = 0; i < Members.Count; i++)
{
string memberName = Members[i].Name;
if (memberName.Length == count && string.CompareOrdinal(value, index, memberName, 0, count) == 0)
{
return Values[i];
}
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.InvalidEnumValueOnRead, value.Substring(index, count), DataContract.GetClrTypeFullName(UnderlyingType))));
}
internal string GetStringFromEnumValue(long value)
{
if (IsULong)
{
return XmlConvert.ToString((ulong)value);
}
else
{
return XmlConvert.ToString(value);
}
}
internal long GetEnumValueFromString(string value)
{
if (IsULong)
{
return (long)XmlConverter.ToUInt64(value);
}
else
{
return XmlConverter.ToInt64(value);
}
}
internal override bool Equals(object other, Dictionary<DataContractPairKey, object> checkedContracts)
{
if (IsEqualOrChecked(other, checkedContracts))
{
return true;
}
if (base.Equals(other, null))
{
EnumDataContract dataContract = other as EnumDataContract;
if (dataContract != null)
{
if (Members.Count != dataContract.Members.Count || Values.Count != dataContract.Values.Count)
{
return false;
}
string[] memberNames1 = new string[Members.Count], memberNames2 = new string[Members.Count];
for (int i = 0; i < Members.Count; i++)
{
memberNames1[i] = Members[i].Name;
memberNames2[i] = dataContract.Members[i].Name;
}
Array.Sort(memberNames1);
Array.Sort(memberNames2);
for (int i = 0; i < Members.Count; i++)
{
if (memberNames1[i] != memberNames2[i])
{
return false;
}
}
return (IsFlags == dataContract.IsFlags);
}
}
return false;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
{
WriteEnumValue(xmlWriter, obj);
}
public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
{
object obj = ReadEnumValue(xmlReader);
if (context != null)
{
context.AddNewObject(obj);
}
return obj;
}
}
}

View File

@@ -0,0 +1,38 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
using System;
using System.Collections.ObjectModel;
namespace Compat.Runtime.Serialization
{
public class ExportOptions
{
private Collection<Type> knownTypes;
private IDataContractSurrogate dataContractSurrogate;
public IDataContractSurrogate DataContractSurrogate
{
get => dataContractSurrogate;
set => dataContractSurrogate = value;
}
internal IDataContractSurrogate GetSurrogate()
{
return dataContractSurrogate;
}
public Collection<Type> KnownTypes
{
get
{
if (knownTypes == null)
{
knownTypes = new Collection<Type>();
}
return knownTypes;
}
}
}
}

View File

@@ -0,0 +1,13 @@
namespace Compat.Runtime.Serialization
{
internal class ExtensionDataMember
{
public string Name { get; set; }
public string Namespace { get; set; }
public IDataNode Value { get; set; }
public int MemberIndex { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace Compat.Runtime.Serialization
{
public sealed class ExtensionDataObject
{
internal ExtensionDataObject()
{
}
internal IList<ExtensionDataMember> Members { get; set; }
}
}

View File

@@ -0,0 +1,877 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
using SerializationException = System.Runtime.Serialization.SerializationException;
namespace Compat.Runtime.Serialization
{
internal class ExtensionDataReader : XmlReader
{
private enum ExtensionDataNodeType
{
None,
Element,
EndElement,
Text,
Xml,
ReferencedElement,
NullElement,
}
private readonly Hashtable cache = new Hashtable();
private ElementData[] elements;
private ElementData element;
private ElementData nextElement;
private ReadState readState = ReadState.Initial;
private ExtensionDataNodeType internalNodeType;
private XmlNodeType nodeType;
private int depth;
private string localName;
private string ns;
private string prefix;
private string value;
private int attributeCount;
private int attributeIndex;
private XmlNodeReader xmlNodeReader;
private Queue<IDataNode> deserializedDataNodes;
private readonly XmlObjectSerializerReadContext context;
private static readonly Dictionary<string, string> nsToPrefixTable;
private static readonly Dictionary<string, string> prefixToNsTable;
static ExtensionDataReader()
{
nsToPrefixTable = new Dictionary<string, string>();
prefixToNsTable = new Dictionary<string, string>();
AddPrefix(Globals.XsiPrefix, Globals.SchemaInstanceNamespace);
AddPrefix(Globals.SerPrefix, Globals.SerializationNamespace);
AddPrefix(string.Empty, string.Empty);
}
internal ExtensionDataReader(XmlObjectSerializerReadContext context)
{
attributeIndex = -1;
this.context = context;
}
internal void SetDeserializedValue(object obj)
{
IDataNode deserializedDataNode = (deserializedDataNodes == null || deserializedDataNodes.Count == 0) ? null : deserializedDataNodes.Dequeue();
if (deserializedDataNode != null && !(obj is IDataNode))
{
deserializedDataNode.Value = obj;
deserializedDataNode.IsFinalValue = true;
}
}
internal IDataNode GetCurrentNode()
{
IDataNode retVal = element.dataNode;
Skip();
return retVal;
}
internal void SetDataNode(IDataNode dataNode, string name, string ns)
{
SetNextElement(dataNode, name, ns, null);
element = nextElement;
nextElement = null;
SetElement();
}
internal void Reset()
{
localName = null;
ns = null;
prefix = null;
value = null;
attributeCount = 0;
attributeIndex = -1;
depth = 0;
element = null;
nextElement = null;
elements = null;
deserializedDataNodes = null;
}
private bool IsXmlDataNode => (internalNodeType == ExtensionDataNodeType.Xml);
public override XmlNodeType NodeType => IsXmlDataNode ? xmlNodeReader.NodeType : nodeType;
public override string LocalName => IsXmlDataNode ? xmlNodeReader.LocalName : localName;
public override string NamespaceURI => IsXmlDataNode ? xmlNodeReader.NamespaceURI : ns;
public override string Prefix => IsXmlDataNode ? xmlNodeReader.Prefix : prefix;
public override string Value => IsXmlDataNode ? xmlNodeReader.Value : value;
public override int Depth => IsXmlDataNode ? xmlNodeReader.Depth : depth;
public override int AttributeCount => IsXmlDataNode ? xmlNodeReader.AttributeCount : attributeCount;
public override bool EOF => IsXmlDataNode ? xmlNodeReader.EOF : (readState == ReadState.EndOfFile);
public override ReadState ReadState => IsXmlDataNode ? xmlNodeReader.ReadState : readState;
public override bool IsEmptyElement => IsXmlDataNode ? xmlNodeReader.IsEmptyElement : false;
public override bool IsDefault => IsXmlDataNode ? xmlNodeReader.IsDefault : base.IsDefault;
public override char QuoteChar => IsXmlDataNode ? xmlNodeReader.QuoteChar : base.QuoteChar;
public override XmlSpace XmlSpace => IsXmlDataNode ? xmlNodeReader.XmlSpace : base.XmlSpace;
public override string XmlLang => IsXmlDataNode ? xmlNodeReader.XmlLang : base.XmlLang;
public override string this[int i] => IsXmlDataNode ? xmlNodeReader[i] : GetAttribute(i);
public override string this[string name] => IsXmlDataNode ? xmlNodeReader[name] : GetAttribute(name);
public override string this[string name, string namespaceURI] => IsXmlDataNode ? xmlNodeReader[name, namespaceURI] : GetAttribute(name, namespaceURI);
public override bool MoveToFirstAttribute()
{
if (IsXmlDataNode)
{
return xmlNodeReader.MoveToFirstAttribute();
}
if (attributeCount == 0)
{
return false;
}
MoveToAttribute(0);
return true;
}
public override bool MoveToNextAttribute()
{
if (IsXmlDataNode)
{
return xmlNodeReader.MoveToNextAttribute();
}
if (attributeIndex + 1 >= attributeCount)
{
return false;
}
MoveToAttribute(attributeIndex + 1);
return true;
}
public override void MoveToAttribute(int index)
{
if (IsXmlDataNode)
{
xmlNodeReader.MoveToAttribute(index);
}
else
{
if (index < 0 || index >= attributeCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.InvalidXmlDeserializingExtensionData));
}
nodeType = XmlNodeType.Attribute;
AttributeData attribute = element.attributes[index];
localName = attribute.localName;
ns = attribute.ns;
prefix = attribute.prefix;
value = attribute.value;
attributeIndex = index;
}
}
public override string GetAttribute(string name, string namespaceURI)
{
if (IsXmlDataNode)
{
return xmlNodeReader.GetAttribute(name, namespaceURI);
}
for (int i = 0; i < element.attributeCount; i++)
{
AttributeData attribute = element.attributes[i];
if (attribute.localName == name && attribute.ns == namespaceURI)
{
return attribute.value;
}
}
return null;
}
public override bool MoveToAttribute(string name, string namespaceURI)
{
if (IsXmlDataNode)
{
return xmlNodeReader.MoveToAttribute(name, ns);
}
for (int i = 0; i < element.attributeCount; i++)
{
AttributeData attribute = element.attributes[i];
if (attribute.localName == name && attribute.ns == namespaceURI)
{
MoveToAttribute(i);
return true;
}
}
return false;
}
public override bool MoveToElement()
{
if (IsXmlDataNode)
{
return xmlNodeReader.MoveToElement();
}
if (nodeType != XmlNodeType.Attribute)
{
return false;
}
SetElement();
return true;
}
private void SetElement()
{
nodeType = XmlNodeType.Element;
localName = element.localName;
ns = element.ns;
prefix = element.prefix;
value = string.Empty;
attributeCount = element.attributeCount;
attributeIndex = -1;
}
public override string LookupNamespace(string prefix)
{
if (IsXmlDataNode)
{
return xmlNodeReader.LookupNamespace(prefix);
}
if (!prefixToNsTable.TryGetValue(prefix, out string ns))
{
return null;
}
return ns;
}
public override void Skip()
{
if (IsXmlDataNode)
{
xmlNodeReader.Skip();
}
else
{
if (ReadState != ReadState.Interactive)
{
return;
}
MoveToElement();
if (IsElementNode(internalNodeType))
{
int depth = 1;
while (depth != 0)
{
if (!Read())
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.InvalidXmlDeserializingExtensionData));
}
if (IsElementNode(internalNodeType))
{
depth++;
}
else if (internalNodeType == ExtensionDataNodeType.EndElement)
{
ReadEndElement();
depth--;
}
}
}
else
{
Read();
}
}
}
private bool IsElementNode(ExtensionDataNodeType nodeType)
{
return (nodeType == ExtensionDataNodeType.Element ||
nodeType == ExtensionDataNodeType.ReferencedElement ||
nodeType == ExtensionDataNodeType.NullElement);
}
public override void Close()
{
if (IsXmlDataNode)
{
xmlNodeReader.Close();
}
else
{
Reset();
readState = ReadState.Closed;
}
}
public override bool Read()
{
if (nodeType == XmlNodeType.Attribute && MoveToNextAttribute())
{
return true;
}
MoveNext(element.dataNode);
switch (internalNodeType)
{
case ExtensionDataNodeType.Element:
case ExtensionDataNodeType.ReferencedElement:
case ExtensionDataNodeType.NullElement:
PushElement();
SetElement();
break;
case ExtensionDataNodeType.Text:
nodeType = XmlNodeType.Text;
prefix = string.Empty;
ns = string.Empty;
localName = string.Empty;
attributeCount = 0;
attributeIndex = -1;
break;
case ExtensionDataNodeType.EndElement:
nodeType = XmlNodeType.EndElement;
prefix = string.Empty;
ns = string.Empty;
localName = string.Empty;
value = string.Empty;
attributeCount = 0;
attributeIndex = -1;
PopElement();
break;
case ExtensionDataNodeType.None:
if (depth != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.InvalidXmlDeserializingExtensionData));
}
nodeType = XmlNodeType.None;
prefix = string.Empty;
ns = string.Empty;
localName = string.Empty;
value = string.Empty;
attributeCount = 0;
readState = ReadState.EndOfFile;
return false;
case ExtensionDataNodeType.Xml:
// do nothing
break;
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.InvalidStateInExtensionDataReader));
}
readState = ReadState.Interactive;
return true;
}
public override string Name
{
get
{
if (IsXmlDataNode)
{
return xmlNodeReader.Name;
}
Fx.Assert("ExtensionDataReader Name property should only be called for IXmlSerializable");
return string.Empty;
}
}
public override bool HasValue
{
get
{
if (IsXmlDataNode)
{
return xmlNodeReader.HasValue;
}
Fx.Assert("ExtensionDataReader HasValue property should only be called for IXmlSerializable");
return false;
}
}
public override string BaseURI
{
get
{
if (IsXmlDataNode)
{
return xmlNodeReader.BaseURI;
}
Fx.Assert("ExtensionDataReader BaseURI property should only be called for IXmlSerializable");
return string.Empty;
}
}
public override XmlNameTable NameTable
{
get
{
if (IsXmlDataNode)
{
return xmlNodeReader.NameTable;
}
Fx.Assert("ExtensionDataReader NameTable property should only be called for IXmlSerializable");
return null;
}
}
public override string GetAttribute(string name)
{
if (IsXmlDataNode)
{
return xmlNodeReader.GetAttribute(name);
}
Fx.Assert("ExtensionDataReader GetAttribute method should only be called for IXmlSerializable");
return null;
}
public override string GetAttribute(int i)
{
if (IsXmlDataNode)
{
return xmlNodeReader.GetAttribute(i);
}
Fx.Assert("ExtensionDataReader GetAttribute method should only be called for IXmlSerializable");
return null;
}
public override bool MoveToAttribute(string name)
{
if (IsXmlDataNode)
{
return xmlNodeReader.MoveToAttribute(name);
}
Fx.Assert("ExtensionDataReader MoveToAttribute method should only be called for IXmlSerializable");
return false;
}
public override void ResolveEntity()
{
if (IsXmlDataNode)
{
xmlNodeReader.ResolveEntity();
}
else
{
Fx.Assert("ExtensionDataReader ResolveEntity method should only be called for IXmlSerializable");
}
}
public override bool ReadAttributeValue()
{
if (IsXmlDataNode)
{
return xmlNodeReader.ReadAttributeValue();
}
Fx.Assert("ExtensionDataReader ReadAttributeValue method should only be called for IXmlSerializable");
return false;
}
private void MoveNext(IDataNode dataNode)
{
switch (internalNodeType)
{
case ExtensionDataNodeType.Text:
case ExtensionDataNodeType.ReferencedElement:
case ExtensionDataNodeType.NullElement:
internalNodeType = ExtensionDataNodeType.EndElement;
return;
default:
Type dataNodeType = dataNode.DataType;
if (dataNodeType == Globals.TypeOfClassDataNode)
{
MoveNextInClass((ClassDataNode)dataNode);
}
else if (dataNodeType == Globals.TypeOfCollectionDataNode)
{
MoveNextInCollection((CollectionDataNode)dataNode);
}
else if (dataNodeType == Globals.TypeOfISerializableDataNode)
{
MoveNextInISerializable((ISerializableDataNode)dataNode);
}
else if (dataNodeType == Globals.TypeOfXmlDataNode)
{
MoveNextInXml((XmlDataNode)dataNode);
}
else if (dataNode.Value != null)
{
MoveToDeserializedObject(dataNode);
}
else
{
Fx.Assert("Encountered invalid data node when deserializing unknown data");
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.InvalidStateInExtensionDataReader));
}
break;
}
}
private void SetNextElement(IDataNode node, string name, string ns, string prefix)
{
internalNodeType = ExtensionDataNodeType.Element;
nextElement = GetNextElement();
nextElement.localName = name;
nextElement.ns = ns;
nextElement.prefix = prefix;
if (node == null)
{
nextElement.attributeCount = 0;
nextElement.AddAttribute(Globals.XsiPrefix, Globals.SchemaInstanceNamespace, Globals.XsiNilLocalName, Globals.True);
internalNodeType = ExtensionDataNodeType.NullElement;
}
else if (!CheckIfNodeHandled(node))
{
AddDeserializedDataNode(node);
node.GetData(nextElement);
if (node is XmlDataNode)
{
MoveNextInXml((XmlDataNode)node);
}
}
}
private void AddDeserializedDataNode(IDataNode node)
{
if (node.Id != Globals.NewObjectId && (node.Value == null || !node.IsFinalValue))
{
if (deserializedDataNodes == null)
{
deserializedDataNodes = new Queue<IDataNode>();
}
deserializedDataNodes.Enqueue(node);
}
}
private bool CheckIfNodeHandled(IDataNode node)
{
bool handled = false;
if (node.Id != Globals.NewObjectId)
{
handled = (cache[node] != null);
if (handled)
{
if (nextElement == null)
{
nextElement = GetNextElement();
}
nextElement.attributeCount = 0;
nextElement.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.RefLocalName, node.Id.ToString(NumberFormatInfo.InvariantInfo));
nextElement.AddAttribute(Globals.XsiPrefix, Globals.SchemaInstanceNamespace, Globals.XsiNilLocalName, Globals.True);
internalNodeType = ExtensionDataNodeType.ReferencedElement;
}
else
{
cache.Add(node, node);
}
}
return handled;
}
private void MoveNextInClass(ClassDataNode dataNode)
{
if (dataNode.Members != null && element.childElementIndex < dataNode.Members.Count)
{
if (element.childElementIndex == 0)
{
context.IncrementItemCount(-dataNode.Members.Count);
}
ExtensionDataMember member = dataNode.Members[element.childElementIndex++];
SetNextElement(member.Value, member.Name, member.Namespace, GetPrefix(member.Namespace));
}
else
{
internalNodeType = ExtensionDataNodeType.EndElement;
element.childElementIndex = 0;
}
}
private void MoveNextInCollection(CollectionDataNode dataNode)
{
if (dataNode.Items != null && element.childElementIndex < dataNode.Items.Count)
{
if (element.childElementIndex == 0)
{
context.IncrementItemCount(-dataNode.Items.Count);
}
IDataNode item = dataNode.Items[element.childElementIndex++];
SetNextElement(item, dataNode.ItemName, dataNode.ItemNamespace, GetPrefix(dataNode.ItemNamespace));
}
else
{
internalNodeType = ExtensionDataNodeType.EndElement;
element.childElementIndex = 0;
}
}
private void MoveNextInISerializable(ISerializableDataNode dataNode)
{
if (dataNode.Members != null && element.childElementIndex < dataNode.Members.Count)
{
if (element.childElementIndex == 0)
{
context.IncrementItemCount(-dataNode.Members.Count);
}
ISerializableDataMember member = dataNode.Members[element.childElementIndex++];
SetNextElement(member.Value, member.Name, string.Empty, string.Empty);
}
else
{
internalNodeType = ExtensionDataNodeType.EndElement;
element.childElementIndex = 0;
}
}
private void MoveNextInXml(XmlDataNode dataNode)
{
if (IsXmlDataNode)
{
xmlNodeReader.Read();
if (xmlNodeReader.Depth == 0)
{
internalNodeType = ExtensionDataNodeType.EndElement;
xmlNodeReader = null;
}
}
else
{
internalNodeType = ExtensionDataNodeType.Xml;
if (element == null)
{
element = nextElement;
}
else
{
PushElement();
}
XmlNode wrapperElement = XmlObjectSerializerReadContext.CreateWrapperXmlElement(dataNode.OwnerDocument,
dataNode.XmlAttributes, dataNode.XmlChildNodes, element.prefix, element.localName, element.ns);
for (int i = 0; i < element.attributeCount; i++)
{
AttributeData a = element.attributes[i];
XmlAttribute xmlAttr = dataNode.OwnerDocument.CreateAttribute(a.prefix, a.localName, a.ns);
xmlAttr.Value = a.value;
wrapperElement.Attributes.Append(xmlAttr);
}
xmlNodeReader = new XmlNodeReader(wrapperElement);
xmlNodeReader.Read();
}
}
private void MoveToDeserializedObject(IDataNode dataNode)
{
Type type = dataNode.DataType;
bool isTypedNode = true;
if (type == Globals.TypeOfObject)
{
type = dataNode.Value.GetType();
if (type == Globals.TypeOfObject)
{
internalNodeType = ExtensionDataNodeType.EndElement;
return;
}
isTypedNode = false;
}
if (!MoveToText(type, dataNode, isTypedNode))
{
if (dataNode.IsFinalValue)
{
internalNodeType = ExtensionDataNodeType.EndElement;
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.Format(SR.InvalidDataNode, DataContract.GetClrTypeFullName(type))));
}
}
}
private bool MoveToText(Type type, IDataNode dataNode, bool isTypedNode)
{
bool handled = true;
switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<bool>)dataNode).GetValue() : (bool)dataNode.Value);
break;
case TypeCode.Char:
value = XmlConvert.ToString((int)(isTypedNode ? ((DataNode<char>)dataNode).GetValue() : (char)dataNode.Value));
break;
case TypeCode.Byte:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<byte>)dataNode).GetValue() : (byte)dataNode.Value);
break;
case TypeCode.Int16:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<short>)dataNode).GetValue() : (short)dataNode.Value);
break;
case TypeCode.Int32:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<int>)dataNode).GetValue() : (int)dataNode.Value);
break;
case TypeCode.Int64:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<long>)dataNode).GetValue() : (long)dataNode.Value);
break;
case TypeCode.Single:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<float>)dataNode).GetValue() : (float)dataNode.Value);
break;
case TypeCode.Double:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<double>)dataNode).GetValue() : (double)dataNode.Value);
break;
case TypeCode.Decimal:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<decimal>)dataNode).GetValue() : (decimal)dataNode.Value);
break;
case TypeCode.DateTime:
DateTime dateTime = isTypedNode ? ((DataNode<DateTime>)dataNode).GetValue() : (DateTime)dataNode.Value;
value = dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffffffK", DateTimeFormatInfo.InvariantInfo);
break;
case TypeCode.String:
value = isTypedNode ? ((DataNode<string>)dataNode).GetValue() : (string)dataNode.Value;
break;
case TypeCode.SByte:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<sbyte>)dataNode).GetValue() : (sbyte)dataNode.Value);
break;
case TypeCode.UInt16:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<ushort>)dataNode).GetValue() : (ushort)dataNode.Value);
break;
case TypeCode.UInt32:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<uint>)dataNode).GetValue() : (uint)dataNode.Value);
break;
case TypeCode.UInt64:
value = XmlConvert.ToString(isTypedNode ? ((DataNode<ulong>)dataNode).GetValue() : (ulong)dataNode.Value);
break;
case TypeCode.Object:
default:
if (type == Globals.TypeOfByteArray)
{
byte[] bytes = isTypedNode ? ((DataNode<byte[]>)dataNode).GetValue() : (byte[])dataNode.Value;
value = (bytes == null) ? string.Empty : Convert.ToBase64String(bytes);
}
else if (type == Globals.TypeOfTimeSpan)
{
value = XmlConvert.ToString(isTypedNode ? ((DataNode<TimeSpan>)dataNode).GetValue() : (TimeSpan)dataNode.Value);
}
else if (type == Globals.TypeOfGuid)
{
Guid guid = isTypedNode ? ((DataNode<Guid>)dataNode).GetValue() : (Guid)dataNode.Value;
value = guid.ToString();
}
else if (type == Globals.TypeOfUri)
{
Uri uri = isTypedNode ? ((DataNode<Uri>)dataNode).GetValue() : (Uri)dataNode.Value;
value = uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
}
else
{
handled = false;
}
break;
}
if (handled)
{
internalNodeType = ExtensionDataNodeType.Text;
}
return handled;
}
private void PushElement()
{
GrowElementsIfNeeded();
elements[depth++] = element;
if (nextElement == null)
{
element = GetNextElement();
}
else
{
element = nextElement;
nextElement = null;
}
}
private void PopElement()
{
prefix = element.prefix;
localName = element.localName;
ns = element.ns;
if (depth == 0)
{
return;
}
depth--;
if (elements != null)
{
element = elements[depth];
}
}
private void GrowElementsIfNeeded()
{
if (elements == null)
{
elements = new ElementData[8];
}
else if (elements.Length == depth)
{
ElementData[] newElements = new ElementData[elements.Length * 2];
Array.Copy(elements, 0, newElements, 0, elements.Length);
elements = newElements;
}
}
private ElementData GetNextElement()
{
int nextDepth = depth + 1;
return (elements == null || elements.Length <= nextDepth || elements[nextDepth] == null)
? new ElementData() : elements[nextDepth];
}
internal static string GetPrefix(string ns)
{
ns = ns ?? string.Empty;
if (!nsToPrefixTable.TryGetValue(ns, out string prefix))
{
lock (nsToPrefixTable)
{
if (!nsToPrefixTable.TryGetValue(ns, out prefix))
{
prefix = (ns == null || ns.Length == 0) ? string.Empty : "p" + nsToPrefixTable.Count;
AddPrefix(prefix, ns);
}
}
}
return prefix;
}
private static void AddPrefix(string prefix, string ns)
{
nsToPrefixTable.Add(ns, prefix);
prefixToNsTable.Add(prefix, ns);
}
}
}

View File

@@ -0,0 +1,120 @@
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal class GenericInfo : IGenericNameProvider
{
private readonly string genericTypeName;
private readonly XmlQualifiedName stableName;
private List<GenericInfo> paramGenericInfos;
private readonly List<int> nestedParamCounts;
internal GenericInfo(XmlQualifiedName stableName, string genericTypeName)
{
this.stableName = stableName;
this.genericTypeName = genericTypeName;
nestedParamCounts = new List<int>
{
0
};
}
internal void Add(GenericInfo actualParamInfo)
{
if (paramGenericInfos == null)
{
paramGenericInfos = new List<GenericInfo>();
}
paramGenericInfos.Add(actualParamInfo);
}
internal void AddToLevel(int level, int count)
{
if (level >= nestedParamCounts.Count)
{
do
{
nestedParamCounts.Add((level == nestedParamCounts.Count) ? count : 0);
} while (level >= nestedParamCounts.Count);
}
else
{
nestedParamCounts[level] = nestedParamCounts[level] + count;
}
}
internal XmlQualifiedName GetExpandedStableName()
{
if (paramGenericInfos == null)
{
return stableName;
}
return new XmlQualifiedName(DataContract.EncodeLocalName(DataContract.ExpandGenericParameters(XmlConvert.DecodeName(stableName.Name), this)), stableName.Namespace);
}
internal string GetStableNamespace()
{
return stableName.Namespace;
}
internal XmlQualifiedName StableName => stableName;
internal IList<GenericInfo> Parameters => paramGenericInfos;
public int GetParameterCount()
{
return paramGenericInfos.Count;
}
public IList<int> GetNestedParameterCounts()
{
return nestedParamCounts;
}
public string GetParameterName(int paramIndex)
{
return paramGenericInfos[paramIndex].GetExpandedStableName().Name;
}
public string GetNamespaces()
{
StringBuilder namespaces = new StringBuilder();
for (int j = 0; j < paramGenericInfos.Count; j++)
{
namespaces.Append(" ").Append(paramGenericInfos[j].GetStableNamespace());
}
return namespaces.ToString();
}
public string GetGenericTypeName()
{
return genericTypeName;
}
public bool ParametersFromBuiltInNamespaces
{
get
{
bool parametersFromBuiltInNamespaces = true;
for (int j = 0; j < paramGenericInfos.Count; j++)
{
if (parametersFromBuiltInNamespaces)
{
parametersFromBuiltInNamespaces = DataContract.IsBuiltInNamespace(paramGenericInfos[j].GetStableNamespace());
}
else
{
break;
}
}
return parametersFromBuiltInNamespaces;
}
}
}
}

View File

@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal interface IGenericNameProvider
{
int GetParameterCount();
IList<int> GetNestedParameterCounts();
string GetParameterName(int paramIndex);
string GetNamespaces();
string GetGenericTypeName();
bool ParametersFromBuiltInNamespaces { get; }
}
internal class GenericNameProvider : IGenericNameProvider
{
private readonly string _genericTypeName;
private readonly object[] _genericParams; //Type or DataContract
private readonly IList<int> _nestedParamCounts;
internal GenericNameProvider(Type type)
: this(DataContract.GetClrTypeFullName(type.GetGenericTypeDefinition()), type.GetGenericArguments())
{
}
internal GenericNameProvider(string genericTypeName, object[] genericParams)
{
_genericTypeName = genericTypeName;
_genericParams = new object[genericParams.Length];
genericParams.CopyTo(_genericParams, 0);
DataContract.GetClrNameAndNamespace(genericTypeName, out string name, out string ns);
_nestedParamCounts = DataContract.GetDataContractNameForGenericName(name, null);
}
public int GetParameterCount()
{
return _genericParams.Length;
}
public IList<int> GetNestedParameterCounts()
{
return _nestedParamCounts;
}
public string GetParameterName(int paramIndex)
{
return GetStableName(paramIndex).Name;
}
public string GetNamespaces()
{
StringBuilder namespaces = new StringBuilder();
for (int j = 0; j < GetParameterCount(); j++)
{
namespaces.Append(" ").Append(GetStableName(j).Namespace);
}
return namespaces.ToString();
}
public string GetGenericTypeName()
{
return _genericTypeName;
}
public bool ParametersFromBuiltInNamespaces
{
get
{
bool parametersFromBuiltInNamespaces = true;
for (int j = 0; j < GetParameterCount(); j++)
{
if (parametersFromBuiltInNamespaces)
{
parametersFromBuiltInNamespaces = DataContract.IsBuiltInNamespace(GetStableName(j).Namespace);
}
else
{
break;
}
}
return parametersFromBuiltInNamespaces;
}
}
private XmlQualifiedName GetStableName(int i)
{
object o = _genericParams[i];
XmlQualifiedName qname = o as XmlQualifiedName;
if (qname == null)
{
Type paramType = o as Type;
if (paramType != null)
{
_genericParams[i] = qname = DataContract.GetStableName(paramType);
}
else
{
_genericParams[i] = qname = ((DataContract)o).StableName;
}
}
return qname;
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
namespace Compat.Runtime.Serialization
{
internal sealed class GenericParameterDataContract : DataContract
{
private readonly GenericParameterDataContractCriticalHelper _helper;
internal GenericParameterDataContract(Type type)
: base(new GenericParameterDataContractCriticalHelper(type))
{
_helper = base.Helper as GenericParameterDataContractCriticalHelper;
}
internal int ParameterPosition => _helper.ParameterPosition;
internal override bool IsBuiltInDataContract => true;
private class GenericParameterDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
private readonly int parameterPosition;
internal GenericParameterDataContractCriticalHelper(Type type)
: base(type)
{
SetDataContractName(DataContract.GetStableName(type));
parameterPosition = type.GenericParameterPosition;
}
internal int ParameterPosition => parameterPosition;
}
internal override DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary<DataContract, DataContract> boundContracts)
{
return paramContracts[ParameterPosition];
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
using System.Collections.Generic;
namespace Compat.Runtime.Serialization
{
internal class HybridObjectCache
{
private Dictionary<string, object> _objectDictionary;
private Dictionary<string, object> _referencedObjectDictionary;
internal HybridObjectCache()
{
}
internal void Add(string id, object obj)
{
if (_objectDictionary == null)
{
_objectDictionary = new Dictionary<string, object>();
}
if (_objectDictionary.TryGetValue(id, out object existingObject))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.MultipleIdDefinition, id)));
}
_objectDictionary.Add(id, obj);
}
internal void Remove(string id)
{
if (_objectDictionary != null)
{
_objectDictionary.Remove(id);
}
}
internal object GetObject(string id)
{
if (_referencedObjectDictionary == null)
{
_referencedObjectDictionary = new Dictionary<string, object>
{
{ id, null }
};
}
else if (!_referencedObjectDictionary.ContainsKey(id))
{
_referencedObjectDictionary.Add(id, null);
}
if (_objectDictionary != null)
{
_objectDictionary.TryGetValue(id, out object obj);
return obj;
}
return null;
}
internal bool IsObjectReferenced(string id)
{
if (_referencedObjectDictionary != null)
{
return _referencedObjectDictionary.ContainsKey(id);
}
return false;
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Reflection;
using System.Collections.ObjectModel;
namespace Compat.Runtime.Serialization
{
public interface IDataContractSurrogate
{
Type GetDataContractType(Type type);
object GetObjectToSerialize(object obj, Type targetType);
object GetDeserializedObject(object obj, Type targetType);
object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType);
object GetCustomDataToExport(Type clrType, Type dataContractType);
void GetKnownCustomDataTypes(Collection<Type> customDataTypes);
Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData);
}
}

View File

@@ -0,0 +1,21 @@
using System;
namespace Compat.Runtime.Serialization
{
internal interface IDataNode
{
Type DataType { get; }
object Value { get; set; } // boxes for primitives
string DataContractName { get; set; }
string DataContractNamespace { get; set; }
string ClrTypeName { get; set; }
string ClrAssemblyName { get; set; }
string Id { get; set; }
bool PreservesReferences { get; }
// NOTE: consider moving below APIs to DataNode<T> if IDataNode API is made public
void GetData(ElementData element);
bool IsFinalValue { get; set; }
void Clear();
}
}

View File

@@ -0,0 +1,9 @@
namespace Compat.Runtime.Serialization
{
internal class ISerializableDataMember
{
internal string Name { get; set; }
internal IDataNode Value { get; set; }
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections.Generic;
namespace Compat.Runtime.Serialization
{
internal class ISerializableDataNode : DataNode<object>
{
private string _factoryTypeName;
private string _factoryTypeNamespace;
private IList<ISerializableDataMember> _members;
internal ISerializableDataNode()
{
dataType = Globals.TypeOfISerializableDataNode;
}
internal string FactoryTypeName
{
get => _factoryTypeName;
set => _factoryTypeName = value;
}
internal string FactoryTypeNamespace
{
get => _factoryTypeNamespace;
set => _factoryTypeNamespace = value;
}
internal IList<ISerializableDataMember> Members
{
get => _members;
set => _members = value;
}
public override void GetData(ElementData element)
{
base.GetData(element);
if (FactoryTypeName != null)
{
AddQualifiedNameAttribute(element, Globals.SerPrefix, Globals.ISerializableFactoryTypeLocalName, Globals.SerializationNamespace, FactoryTypeName, FactoryTypeNamespace);
}
}
public override void Clear()
{
base.Clear();
_members = null;
_factoryTypeName = _factoryTypeNamespace = null;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace Compat.Runtime.Serialization
{
internal class IntRef
{
private readonly int _value;
public IntRef(int value)
{
_value = value;
}
public int Value => _value;
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Xml;
using DataContractResolver = System.Runtime.Serialization.DataContractResolver;
namespace Compat.Runtime.Serialization
{
internal sealed class KnownTypeDataContractResolver : DataContractResolver
{
private readonly XmlObjectSerializerContext _context;
internal KnownTypeDataContractResolver(XmlObjectSerializerContext context)
{
Fx.Assert(context != null, "KnownTypeDataContractResolver should not be instantiated with a null context");
_context = context;
}
public override bool TryResolveType(Type type, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
{
if (type == null)
{
typeName = null;
typeNamespace = null;
return false;
}
if (declaredType != null && declaredType.IsInterface && CollectionDataContract.IsCollectionInterface(declaredType))
{
typeName = null;
typeNamespace = null;
return true;
}
DataContract contract = DataContract.GetDataContract(type);
if (_context.IsKnownType(contract, contract.KnownDataContracts, declaredType))
{
typeName = contract.Name;
typeNamespace = contract.Namespace;
return true;
}
else
{
typeName = null;
typeNamespace = null;
return false;
}
}
public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
{
if (typeName == null || typeNamespace == null)
{
return null;
}
return _context.ResolveNameFromKnownTypes(new XmlQualifiedName(typeName, typeNamespace));
}
}
}

View File

@@ -0,0 +1,599 @@
using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters;
using System.Xml;
using IFormatter = System.Runtime.Serialization.IFormatter;
using ISerializationSurrogate = System.Runtime.Serialization.ISerializationSurrogate;
using ISurrogateSelector = System.Runtime.Serialization.ISurrogateSelector;
using SerializationBinder = System.Runtime.Serialization.SerializationBinder;
using SerializationInfo = System.Runtime.Serialization.SerializationInfo;
using StreamingContext = System.Runtime.Serialization.StreamingContext;
using StreamingContextStates = System.Runtime.Serialization.StreamingContextStates;
namespace Compat.Runtime.Serialization
{
public sealed class NetDataContractSerializer : XmlObjectSerializer, IFormatter
{
private XmlDictionaryString rootName;
private XmlDictionaryString rootNamespace;
private StreamingContext context;
private SerializationBinder binder;
private ISurrogateSelector surrogateSelector;
private int maxItemsInObjectGraph;
private bool ignoreExtensionDataObject;
private FormatterAssemblyStyle assemblyFormat;
private DataContract cachedDataContract;
private static readonly Hashtable typeNameCache = new Hashtable();
public NetDataContractSerializer()
: this(new StreamingContext(StreamingContextStates.All))
{
}
public NetDataContractSerializer(StreamingContext context)
: this(context, int.MaxValue, false, FormatterAssemblyStyle.Full, null)
{
}
public NetDataContractSerializer(StreamingContext context,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
FormatterAssemblyStyle assemblyFormat,
ISurrogateSelector surrogateSelector)
{
Initialize(context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
}
public NetDataContractSerializer(string rootName, string rootNamespace)
: this(rootName, rootNamespace, new StreamingContext(StreamingContextStates.All), int.MaxValue, false, FormatterAssemblyStyle.Full, null)
{
}
public NetDataContractSerializer(string rootName, string rootNamespace,
StreamingContext context,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
FormatterAssemblyStyle assemblyFormat,
ISurrogateSelector surrogateSelector)
{
XmlDictionary dictionary = new XmlDictionary(2);
Initialize(dictionary.Add(rootName), dictionary.Add(DataContract.GetNamespace(rootNamespace)), context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
}
public NetDataContractSerializer(XmlDictionaryString rootName, XmlDictionaryString rootNamespace)
: this(rootName, rootNamespace, new StreamingContext(StreamingContextStates.All), int.MaxValue, false, FormatterAssemblyStyle.Full, null)
{
}
public NetDataContractSerializer(XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
StreamingContext context,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
FormatterAssemblyStyle assemblyFormat,
ISurrogateSelector surrogateSelector)
{
Initialize(rootName, rootNamespace, context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
}
private void Initialize(StreamingContext context,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
FormatterAssemblyStyle assemblyFormat,
ISurrogateSelector surrogateSelector)
{
this.context = context;
if (maxItemsInObjectGraph < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxItemsInObjectGraph), SR.ValueMustBeNonNegative));
}
this.maxItemsInObjectGraph = maxItemsInObjectGraph;
this.ignoreExtensionDataObject = ignoreExtensionDataObject;
this.surrogateSelector = surrogateSelector;
AssemblyFormat = assemblyFormat;
}
private void Initialize(XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
StreamingContext context,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
FormatterAssemblyStyle assemblyFormat,
ISurrogateSelector surrogateSelector)
{
Initialize(context, maxItemsInObjectGraph, ignoreExtensionDataObject, assemblyFormat, surrogateSelector);
this.rootName = rootName;
this.rootNamespace = rootNamespace;
}
public StreamingContext Context
{
get => context;
set => context = value;
}
public SerializationBinder Binder
{
get => binder;
set => binder = value;
}
public ISurrogateSelector SurrogateSelector
{
get => surrogateSelector;
set => surrogateSelector = value;
}
public FormatterAssemblyStyle AssemblyFormat
{
get => assemblyFormat;
set
{
if (value != FormatterAssemblyStyle.Full && value != FormatterAssemblyStyle.Simple)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.InvalidAssemblyFormat, value)));
}
assemblyFormat = value;
}
}
public int MaxItemsInObjectGraph => maxItemsInObjectGraph;
public bool IgnoreExtensionDataObject => ignoreExtensionDataObject;
public void Serialize(Stream stream, object graph)
{
base.WriteObject(stream, graph);
}
public object Deserialize(Stream stream)
{
return base.ReadObject(stream);
}
public object Deserialize(XmlReader reader)
{
return base.ReadObject(reader);
}
internal override void InternalWriteObject(XmlWriterDelegator writer, object graph)
{
Hashtable surrogateDataContracts = null;
DataContract contract = GetDataContract(graph, ref surrogateDataContracts);
InternalWriteStartObject(writer, graph, contract);
InternalWriteObjectContent(writer, graph, contract, surrogateDataContracts);
InternalWriteEndObject(writer);
}
public override void WriteObject(XmlWriter writer, object graph)
{
WriteObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
}
public override void WriteStartObject(XmlWriter writer, object graph)
{
WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
}
public override void WriteObjectContent(XmlWriter writer, object graph)
{
WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
}
public override void WriteEndObject(XmlWriter writer)
{
WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
}
public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
{
WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
}
internal override void InternalWriteStartObject(XmlWriterDelegator writer, object graph)
{
Hashtable surrogateDataContracts = null;
DataContract contract = GetDataContract(graph, ref surrogateDataContracts);
InternalWriteStartObject(writer, graph, contract);
}
private void InternalWriteStartObject(XmlWriterDelegator writer, object graph, DataContract contract)
{
WriteRootElement(writer, contract, rootName, rootNamespace, CheckIfNeedsContractNsAtRoot(rootName, rootNamespace, contract));
}
public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
{
WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
}
internal override void InternalWriteObjectContent(XmlWriterDelegator writer, object graph)
{
Hashtable surrogateDataContracts = null;
DataContract contract = GetDataContract(graph, ref surrogateDataContracts);
InternalWriteObjectContent(writer, graph, contract, surrogateDataContracts);
}
private void InternalWriteObjectContent(XmlWriterDelegator writer, object graph, DataContract contract, Hashtable surrogateDataContracts)
{
if (MaxItemsInObjectGraph == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
}
if (IsRootXmlAny(rootName, contract))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.IsAnyNotSupportedByNetDataContractSerializer, contract.UnderlyingType)));
}
else if (graph == null)
{
WriteNull(writer);
}
else
{
Type graphType = graph.GetType();
if (contract.UnderlyingType != graphType)
{
contract = GetDataContract(graph, ref surrogateDataContracts);
}
XmlObjectSerializerWriteContext context = null;
if (contract.CanContainReferences)
{
context = XmlObjectSerializerWriteContext.CreateContext(this, surrogateDataContracts);
context.HandleGraphAtTopLevel(writer, graph, contract);
}
WriteClrTypeInfo(writer, contract, binder);
contract.WriteXmlValue(writer, graph, context);
}
}
// Update the overloads whenever you are changing this method
internal static void WriteClrTypeInfo(XmlWriterDelegator writer, DataContract dataContract, SerializationBinder binder)
{
if (!dataContract.IsISerializable && !(dataContract is SurrogateDataContract))
{
TypeInformation typeInformation = null;
Type clrType = dataContract.OriginalUnderlyingType;
string clrTypeName = null;
string clrAssemblyName = null;
if (binder != null)
{
binder.BindToName(clrType, out clrAssemblyName, out clrTypeName);
}
if (clrTypeName == null)
{
typeInformation = NetDataContractSerializer.GetTypeInformation(clrType);
clrTypeName = typeInformation.FullTypeName;
}
if (clrAssemblyName == null)
{
clrAssemblyName = (typeInformation == null) ?
NetDataContractSerializer.GetTypeInformation(clrType).AssemblyString :
typeInformation.AssemblyString;
// Throw in the [TypeForwardedFrom] case to prevent a partially trusted assembly from forwarding itself to an assembly with higher privileges
if (!UnsafeTypeForwardingEnabled && !clrType.Assembly.IsFullyTrusted && !IsAssemblyNameForwardingSafe(clrType.Assembly.FullName, clrAssemblyName))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.TypeCannotBeForwardedFrom, DataContract.GetClrTypeFullName(clrType), clrType.Assembly.FullName, clrAssemblyName)));
}
}
WriteClrTypeInfo(writer, clrTypeName, clrAssemblyName);
}
}
public static bool UnsafeTypeForwardingEnabled => false;
// Update the overloads whenever you are changing this method
internal static void WriteClrTypeInfo(XmlWriterDelegator writer, Type dataContractType, SerializationBinder binder, string defaultClrTypeName, string defaultClrAssemblyName)
{
string clrTypeName = null;
string clrAssemblyName = null;
if (binder != null)
{
binder.BindToName(dataContractType, out clrAssemblyName, out clrTypeName);
}
if (clrTypeName == null)
{
clrTypeName = defaultClrTypeName;
}
if (clrAssemblyName == null)
{
clrAssemblyName = defaultClrAssemblyName;
}
WriteClrTypeInfo(writer, clrTypeName, clrAssemblyName);
}
// Update the overloads whenever you are changing this method
internal static void WriteClrTypeInfo(
XmlWriterDelegator writer,
Type dataContractType,
SerializationBinder binder,
SerializationInfo serInfo)
{
TypeInformation typeInformation = null;
string clrTypeName = null;
string clrAssemblyName = null;
if (binder != null)
{
binder.BindToName(dataContractType, out clrAssemblyName, out clrTypeName);
}
if (clrTypeName == null)
{
if (serInfo.IsFullTypeNameSetExplicit)
{
clrTypeName = serInfo.FullTypeName;
}
else
{
typeInformation = NetDataContractSerializer.GetTypeInformation(serInfo.ObjectType);
clrTypeName = typeInformation.FullTypeName;
}
}
if (clrAssemblyName == null)
{
if (serInfo.IsAssemblyNameSetExplicit)
{
clrAssemblyName = serInfo.AssemblyName;
}
else
{
clrAssemblyName = (typeInformation == null) ?
NetDataContractSerializer.GetTypeInformation(serInfo.ObjectType).AssemblyString :
typeInformation.AssemblyString;
}
}
WriteClrTypeInfo(writer, clrTypeName, clrAssemblyName);
}
private static void WriteClrTypeInfo(XmlWriterDelegator writer, string clrTypeName, string clrAssemblyName)
{
if (clrTypeName != null)
{
writer.WriteAttributeString(Globals.SerPrefix, DictionaryGlobals.ClrTypeLocalName, DictionaryGlobals.SerializationNamespace, DataContract.GetClrTypeString(clrTypeName));
}
if (clrAssemblyName != null)
{
writer.WriteAttributeString(Globals.SerPrefix, DictionaryGlobals.ClrAssemblyLocalName, DictionaryGlobals.SerializationNamespace, DataContract.GetClrTypeString(clrAssemblyName));
}
}
public override void WriteEndObject(XmlDictionaryWriter writer)
{
WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
}
internal override void InternalWriteEndObject(XmlWriterDelegator writer)
{
writer.WriteEndElement();
}
public override object ReadObject(XmlReader reader)
{
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), true /*verifyObjectName*/);
}
public override object ReadObject(XmlReader reader, bool verifyObjectName)
{
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
}
public override bool IsStartObject(XmlReader reader)
{
return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
}
public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
{
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
}
public override bool IsStartObject(XmlDictionaryReader reader)
{
return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
}
internal override object InternalReadObject(XmlReaderDelegator xmlReader, bool verifyObjectName)
{
if (MaxItemsInObjectGraph == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
}
// verifyObjectName has no effect in SharedType mode
if (!IsStartElement(xmlReader))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationExceptionWithReaderDetails(SR.Format(SR.ExpectingElementAtDeserialize, XmlNodeType.Element), xmlReader));
}
XmlObjectSerializerReadContext context = XmlObjectSerializerReadContext.CreateContext(this);
return context.InternalDeserialize(xmlReader, null, null, null);
}
internal override bool InternalIsStartObject(XmlReaderDelegator reader)
{
return IsStartElement(reader);
}
internal DataContract GetDataContract(object obj, ref Hashtable surrogateDataContracts)
{
return GetDataContract(((obj == null) ? Globals.TypeOfObject : obj.GetType()), ref surrogateDataContracts);
}
internal DataContract GetDataContract(Type type, ref Hashtable surrogateDataContracts)
{
return GetDataContract(type.TypeHandle, type, ref surrogateDataContracts);
}
internal DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type, ref Hashtable surrogateDataContracts)
{
DataContract dataContract = GetDataContractFromSurrogateSelector(surrogateSelector, Context, typeHandle, type, ref surrogateDataContracts);
if (dataContract != null)
{
return dataContract;
}
if (cachedDataContract == null)
{
dataContract = DataContract.GetDataContract(typeHandle, type, SerializationMode.SharedType);
cachedDataContract = dataContract;
return dataContract;
}
DataContract currentCachedDataContract = cachedDataContract;
if (currentCachedDataContract.UnderlyingType.TypeHandle.Equals(typeHandle))
{
return currentCachedDataContract;
}
return DataContract.GetDataContract(typeHandle, type, SerializationMode.SharedType);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static ISerializationSurrogate GetSurrogate(
Type type,
ISurrogateSelector surrogateSelector,
StreamingContext context)
{
return surrogateSelector.GetSurrogate(type, context, out ISurrogateSelector surrogateSelectorNotUsed);
}
internal static DataContract GetDataContractFromSurrogateSelector(
ISurrogateSelector surrogateSelector,
StreamingContext context,
RuntimeTypeHandle typeHandle,
Type type,
ref Hashtable surrogateDataContracts)
{
if (surrogateSelector == null)
{
return null;
}
if (type == null)
{
type = Type.GetTypeFromHandle(typeHandle);
}
DataContract builtInDataContract = DataContract.GetBuiltInDataContract(type);
if (builtInDataContract != null)
{
return builtInDataContract;
}
if (surrogateDataContracts != null)
{
DataContract cachedSurrogateContract = (DataContract)surrogateDataContracts[type];
if (cachedSurrogateContract != null)
{
return cachedSurrogateContract;
}
}
DataContract surrogateContract = null;
ISerializationSurrogate surrogate = GetSurrogate(type, surrogateSelector, context);
if (surrogate != null)
{
surrogateContract = new SurrogateDataContract(type, surrogate);
}
else if (type.IsArray)
{
Type elementType = type.GetElementType();
DataContract itemContract = GetDataContractFromSurrogateSelector(surrogateSelector, context, elementType.TypeHandle, elementType, ref surrogateDataContracts);
if (itemContract == null)
{
itemContract = DataContract.GetDataContract(elementType.TypeHandle, elementType, SerializationMode.SharedType);
}
surrogateContract = new CollectionDataContract(type, itemContract);
}
if (surrogateContract != null)
{
if (surrogateDataContracts == null)
{
surrogateDataContracts = new Hashtable();
}
surrogateDataContracts.Add(type, surrogateContract);
return surrogateContract;
}
return null;
}
internal static TypeInformation GetTypeInformation(Type type)
{
TypeInformation typeInformation = null;
object typeInformationObject = typeNameCache[type];
if (typeInformationObject == null)
{
string assemblyName = DataContract.GetClrAssemblyName(type, out bool hasTypeForwardedFrom);
typeInformation = new TypeInformation(DataContract.GetClrTypeFullNameUsingTypeForwardedFromAttribute(type), assemblyName, hasTypeForwardedFrom);
lock (typeNameCache)
{
typeNameCache[type] = typeInformation;
}
}
else
{
typeInformation = (TypeInformation)typeInformationObject;
}
return typeInformation;
}
private static bool IsAssemblyNameForwardingSafe(string originalAssemblyName, string newAssemblyName)
{
if (originalAssemblyName == newAssemblyName)
{
return true;
}
AssemblyName originalAssembly = new AssemblyName(originalAssemblyName);
AssemblyName newAssembly = new AssemblyName(newAssemblyName);
// mscorlib will get loaded by the runtime regardless of its string casing or its public key token,
// so setting the assembly name to mscorlib is always unsafe
if (string.Equals(newAssembly.Name, Globals.MscorlibAssemblySimpleName, StringComparison.OrdinalIgnoreCase) ||
string.Equals(newAssembly.Name, Globals.MscorlibFileName, StringComparison.OrdinalIgnoreCase))
{
return false;
}
return IsPublicKeyTokenForwardingSafe(originalAssembly.GetPublicKeyToken(), newAssembly.GetPublicKeyToken());
}
private static bool IsPublicKeyTokenForwardingSafe(byte[] sourceToken, byte[] destinationToken)
{
if (sourceToken == null || destinationToken == null || sourceToken.Length == 0 || destinationToken.Length == 0 || sourceToken.Length != destinationToken.Length)
{
return false;
}
for (int i = 0; i < sourceToken.Length; i++)
{
if (sourceToken[i] != destinationToken[i])
{
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
namespace Compat.Runtime.Serialization
{
internal struct ObjectReferenceStack
{
private const int MaximumArraySize = 16;
private const int InitialArraySize = 4;
private int count;
private object[] objectArray;
private bool[] isReferenceArray;
private Dictionary<object, object> objectDictionary;
internal void Push(object obj)
{
if (objectArray == null)
{
objectArray = new object[InitialArraySize];
objectArray[count++] = obj;
}
else if (count < MaximumArraySize)
{
if (count == objectArray.Length)
{
Array.Resize<object>(ref objectArray, objectArray.Length * 2);
}
objectArray[count++] = obj;
}
else
{
if (objectDictionary == null)
{
objectDictionary = new Dictionary<object, object>();
}
objectDictionary.Add(obj, null);
count++;
}
}
internal void EnsureSetAsIsReference(object obj)
{
if (count == 0)
{
return;
}
if (count > MaximumArraySize)
{
if (objectDictionary == null)
{
Fx.Assert("Object reference stack in invalid state");
}
objectDictionary.Remove(obj);
}
else
{
if ((objectArray != null) && objectArray[count - 1] == obj)
{
if (isReferenceArray == null)
{
isReferenceArray = new bool[objectArray.Length];
}
else if (count >= isReferenceArray.Length)
{
Array.Resize<bool>(ref isReferenceArray, objectArray.Length);
}
isReferenceArray[count - 1] = true;
}
}
}
internal void Pop(object obj)
{
if (count > MaximumArraySize)
{
if (objectDictionary == null)
{
Fx.Assert("Object reference stack in invalid state");
}
objectDictionary.Remove(obj);
}
count--;
}
internal bool Contains(object obj)
{
int currentCount = count;
if (currentCount > MaximumArraySize)
{
if (objectDictionary != null && objectDictionary.ContainsKey(obj))
{
return true;
}
currentCount = MaximumArraySize;
}
for (int i = (currentCount - 1); i >= 0; i--)
{
if (Object.ReferenceEquals(obj, objectArray[i]) && isReferenceArray != null && !isReferenceArray[i])
{
return true;
}
}
return false;
}
internal int Count => count;
}
}

View File

@@ -0,0 +1,219 @@
using System;
using System.Runtime.CompilerServices;
namespace Compat.Runtime.Serialization
{
internal class ObjectToIdCache
{
internal int m_currentCount;
internal int[] m_ids;
internal object[] m_objs;
private bool[] m_isWrapped;
public ObjectToIdCache()
{
m_currentCount = 1;
m_ids = new int[GetPrime(1)];
m_objs = new object[m_ids.Length];
m_isWrapped = new bool[m_ids.Length];
}
public int GetId(object obj, ref bool newId)
{
int position = FindElement(obj, out bool isEmpty, out bool isWrapped);
if (!isEmpty)
{
newId = false;
return m_ids[position];
}
if (!newId)
{
return -1;
}
int id = m_currentCount++;
m_objs[position] = obj;
m_ids[position] = id;
m_isWrapped[position] = isWrapped;
if (m_currentCount >= (m_objs.Length - 1))
{
Rehash();
}
return id;
}
// (oldObjId, oldObj-id, newObj-newObjId) => (oldObj-oldObjId, newObj-id, newObjId )
public int ReassignId(int oldObjId, object oldObj, object newObj)
{
int position = FindElement(oldObj, out bool isEmpty, out bool isWrapped);
if (isEmpty)
{
return 0;
}
int id = m_ids[position];
if (oldObjId > 0)
{
m_ids[position] = oldObjId;
}
else
{
RemoveAt(position);
}
position = FindElement(newObj, out isEmpty, out isWrapped);
int newObjId = 0;
if (!isEmpty)
{
newObjId = m_ids[position];
}
m_objs[position] = newObj;
m_ids[position] = id;
m_isWrapped[position] = isWrapped;
return newObjId;
}
private int FindElement(object obj, out bool isEmpty, out bool isWrapped)
{
isWrapped = false;
int position = ComputeStartPosition(obj);
for (int i = position; i != (position - 1); i++)
{
if (m_objs[i] == null)
{
isEmpty = true;
return i;
}
if (m_objs[i] == obj)
{
isEmpty = false;
return i;
}
if (i == (m_objs.Length - 1))
{
isWrapped = true;
i = -1;
}
}
// m_obj must ALWAYS have atleast one slot empty (null).
Fx.Assert("Object table overflow");
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.ObjectTableOverflow));
}
private void RemoveAt(int position)
{
int cacheSize = m_objs.Length;
int lastVacantPosition = position;
for (int next = (position == cacheSize - 1) ? 0 : position + 1; next != position; next++)
{
if (m_objs[next] == null)
{
m_objs[lastVacantPosition] = null;
m_ids[lastVacantPosition] = 0;
m_isWrapped[lastVacantPosition] = false;
return;
}
int nextStartPosition = ComputeStartPosition(m_objs[next]);
// If we wrapped while placing an object, then it must be that the start position wasn't wrapped to begin with
bool isNextStartPositionWrapped = next < position && !m_isWrapped[next];
bool isLastVacantPositionWrapped = lastVacantPosition < position;
// We want to avoid moving objects in the cache if the next bucket position is wrapped, but the last vacant position isn't
// and we want to make sure to move objects in the cache when the last vacant position is wrapped but the next bucket position isn't
if ((nextStartPosition <= lastVacantPosition && !(isNextStartPositionWrapped && !isLastVacantPositionWrapped)) ||
(isLastVacantPositionWrapped && !isNextStartPositionWrapped))
{
m_objs[lastVacantPosition] = m_objs[next];
m_ids[lastVacantPosition] = m_ids[next];
// A wrapped object might become unwrapped if it moves from the front of the array to the end of the array
m_isWrapped[lastVacantPosition] = m_isWrapped[next] && next > lastVacantPosition;
lastVacantPosition = next;
}
if (next == (cacheSize - 1))
{
next = -1;
}
}
// m_obj must ALWAYS have atleast one slot empty (null).
Fx.Assert("Object table overflow");
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.ObjectTableOverflow));
}
private int ComputeStartPosition(object o)
{
return (RuntimeHelpers.GetHashCode(o) & 0x7FFFFFFF) % m_objs.Length;
}
private void Rehash()
{
int size = GetPrime(m_objs.Length * 2);
int[] oldIds = m_ids;
object[] oldObjs = m_objs;
m_ids = new int[size];
m_objs = new object[size];
m_isWrapped = new bool[size];
for (int j = 0; j < oldObjs.Length; j++)
{
object obj = oldObjs[j];
if (obj != null)
{
int position = FindElement(obj, out bool found, out bool isWrapped);
m_objs[position] = obj;
m_ids[position] = oldIds[j];
m_isWrapped[position] = isWrapped;
}
}
}
private static int GetPrime(int min)
{
for (int i = 0; i < primes.Length; i++)
{
int prime = primes[i];
if (prime >= min)
{
return prime;
}
}
//outside of our predefined table.
//compute the hard way.
for (int i = (min | 1); i < int.MaxValue; i += 2)
{
if (IsPrime(i))
{
return i;
}
}
return min;
}
private static bool IsPrime(int candidate)
{
if ((candidate & 1) != 0)
{
int limit = (int)Math.Sqrt(candidate);
for (int divisor = 3; divisor <= limit; divisor += 2)
{
if ((candidate % divisor) == 0)
{
return false;
}
}
return true;
}
return (candidate == 2);
}
internal static readonly int[] primes =
{
3, 7, 17, 37, 89, 197, 431, 919, 1931, 4049, 8419, 17519, 36353,
75431, 156437, 324449, 672827, 1395263, 2893249, 5999471,
};
}
}

View File

@@ -0,0 +1,837 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal abstract class PrimitiveDataContract : DataContract
{
private readonly PrimitiveDataContractCriticalHelper _helper;
protected PrimitiveDataContract(Type type, XmlDictionaryString name, XmlDictionaryString ns)
: base(new PrimitiveDataContractCriticalHelper(type, name, ns))
{
_helper = base.Helper as PrimitiveDataContractCriticalHelper;
}
internal static PrimitiveDataContract GetPrimitiveDataContract(Type type)
{
return DataContract.GetBuiltInDataContract(type) as PrimitiveDataContract;
}
internal static PrimitiveDataContract GetPrimitiveDataContract(string name, string ns)
{
return DataContract.GetBuiltInDataContract(name, ns) as PrimitiveDataContract;
}
internal abstract string WriteMethodName { get; }
internal abstract string ReadMethodName { get; }
internal override XmlDictionaryString TopLevelElementNamespace
{
get => DictionaryGlobals.SerializationNamespace;
set { }
}
internal override bool CanContainReferences => false;
internal override bool IsPrimitive => true;
internal override bool IsBuiltInDataContract => true;
internal MethodInfo XmlFormatWriterMethod
{
get
{
if (_helper.XmlFormatWriterMethod == null)
{
if (UnderlyingType.IsValueType)
{
_helper.XmlFormatWriterMethod = typeof(XmlWriterDelegator).GetMethod(WriteMethodName, Globals.ScanAllMembers, null, new Type[] { UnderlyingType, typeof(XmlDictionaryString), typeof(XmlDictionaryString) }, null);
}
else
{
_helper.XmlFormatWriterMethod = typeof(XmlObjectSerializerWriteContext).GetMethod(WriteMethodName, Globals.ScanAllMembers, null, new Type[] { typeof(XmlWriterDelegator), UnderlyingType, typeof(XmlDictionaryString), typeof(XmlDictionaryString) }, null);
}
}
return _helper.XmlFormatWriterMethod;
}
}
internal MethodInfo XmlFormatContentWriterMethod
{
get
{
if (_helper.XmlFormatContentWriterMethod == null)
{
if (UnderlyingType.IsValueType)
{
_helper.XmlFormatContentWriterMethod = typeof(XmlWriterDelegator).GetMethod(WriteMethodName, Globals.ScanAllMembers, null, new Type[] { UnderlyingType }, null);
}
else
{
_helper.XmlFormatContentWriterMethod = typeof(XmlObjectSerializerWriteContext).GetMethod(WriteMethodName, Globals.ScanAllMembers, null, new Type[] { typeof(XmlWriterDelegator), UnderlyingType }, null);
}
}
return _helper.XmlFormatContentWriterMethod;
}
}
internal MethodInfo XmlFormatReaderMethod
{
get
{
if (_helper.XmlFormatReaderMethod == null)
{
_helper.XmlFormatReaderMethod = typeof(XmlReaderDelegator).GetMethod(ReadMethodName, Globals.ScanAllMembers);
}
return _helper.XmlFormatReaderMethod;
}
}
public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
{
xmlWriter.WriteAnyType(obj);
}
protected object HandleReadValue(object obj, XmlObjectSerializerReadContext context)
{
context.AddNewObject(obj);
return obj;
}
protected bool TryReadNullAtTopLevel(XmlReaderDelegator reader)
{
Attributes attributes = new Attributes();
attributes.Read(reader);
if (attributes.Ref != Globals.NewObjectId)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
XmlObjectSerializer.CreateSerializationException(
SR.Format(SR.CannotDeserializeRefAtTopLevel, attributes.Ref)));
}
if (attributes.XsiNil)
{
reader.Skip();
return true;
}
return false;
}
internal override bool Equals(object other, Dictionary<DataContractPairKey, object> checkedContracts)
{
PrimitiveDataContract dataContract = other as PrimitiveDataContract;
if (dataContract != null)
{
Type thisType = GetType();
Type otherType = other.GetType();
return (thisType.Equals(otherType) || thisType.IsSubclassOf(otherType) || otherType.IsSubclassOf(thisType));
}
return false;
}
private class PrimitiveDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
private MethodInfo xmlFormatWriterMethod;
private MethodInfo xmlFormatContentWriterMethod;
private MethodInfo xmlFormatReaderMethod;
internal PrimitiveDataContractCriticalHelper(Type type, XmlDictionaryString name, XmlDictionaryString ns)
: base(type)
{
SetDataContractName(name, ns);
}
internal MethodInfo XmlFormatWriterMethod
{
get => xmlFormatWriterMethod;
set => xmlFormatWriterMethod = value;
}
internal MethodInfo XmlFormatContentWriterMethod
{
get => xmlFormatContentWriterMethod;
set => xmlFormatContentWriterMethod = value;
}
internal MethodInfo XmlFormatReaderMethod
{
get => xmlFormatReaderMethod;
set => xmlFormatReaderMethod = value;
}
}
}
internal class CharDataContract : PrimitiveDataContract
{
internal CharDataContract()
: this(DictionaryGlobals.CharLocalName, DictionaryGlobals.SerializationNamespace)
{
}
internal CharDataContract(XmlDictionaryString name, XmlDictionaryString ns)
: base(typeof(char), name, ns)
{
}
internal override string WriteMethodName => "WriteChar";
internal override string ReadMethodName => "ReadElementContentAsChar";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteChar((char)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsChar()
: HandleReadValue(reader.ReadElementContentAsChar(), context);
}
}
internal class AsmxCharDataContract : CharDataContract
{
internal AsmxCharDataContract() : base(DictionaryGlobals.CharLocalName, DictionaryGlobals.AsmxTypesNamespace) { }
}
internal class BooleanDataContract : PrimitiveDataContract
{
internal BooleanDataContract()
: base(typeof(bool), DictionaryGlobals.BooleanLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteBoolean";
internal override string ReadMethodName => "ReadElementContentAsBoolean";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteBoolean((bool)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsBoolean()
: HandleReadValue(reader.ReadElementContentAsBoolean(), context);
}
}
internal class SignedByteDataContract : PrimitiveDataContract
{
internal SignedByteDataContract()
: base(typeof(sbyte), DictionaryGlobals.SignedByteLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteSignedByte";
internal override string ReadMethodName => "ReadElementContentAsSignedByte";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteSignedByte((sbyte)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsSignedByte()
: HandleReadValue(reader.ReadElementContentAsSignedByte(), context);
}
}
internal class UnsignedByteDataContract : PrimitiveDataContract
{
internal UnsignedByteDataContract()
: base(typeof(byte), DictionaryGlobals.UnsignedByteLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteUnsignedByte";
internal override string ReadMethodName => "ReadElementContentAsUnsignedByte";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteUnsignedByte((byte)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsUnsignedByte()
: HandleReadValue(reader.ReadElementContentAsUnsignedByte(), context);
}
}
internal class ShortDataContract : PrimitiveDataContract
{
internal ShortDataContract()
: base(typeof(short), DictionaryGlobals.ShortLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteShort";
internal override string ReadMethodName => "ReadElementContentAsShort";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteShort((short)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsShort()
: HandleReadValue(reader.ReadElementContentAsShort(), context);
}
}
internal class UnsignedShortDataContract : PrimitiveDataContract
{
internal UnsignedShortDataContract()
: base(typeof(ushort), DictionaryGlobals.UnsignedShortLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteUnsignedShort";
internal override string ReadMethodName => "ReadElementContentAsUnsignedShort";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteUnsignedShort((ushort)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsUnsignedShort()
: HandleReadValue(reader.ReadElementContentAsUnsignedShort(), context);
}
}
internal class IntDataContract : PrimitiveDataContract
{
internal IntDataContract()
: base(typeof(int), DictionaryGlobals.IntLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteInt";
internal override string ReadMethodName => "ReadElementContentAsInt";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteInt((int)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsInt()
: HandleReadValue(reader.ReadElementContentAsInt(), context);
}
}
internal class UnsignedIntDataContract : PrimitiveDataContract
{
internal UnsignedIntDataContract()
: base(typeof(uint), DictionaryGlobals.UnsignedIntLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteUnsignedInt";
internal override string ReadMethodName => "ReadElementContentAsUnsignedInt";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteUnsignedInt((uint)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsUnsignedInt()
: HandleReadValue(reader.ReadElementContentAsUnsignedInt(), context);
}
}
internal class LongDataContract : PrimitiveDataContract
{
internal LongDataContract()
: this(DictionaryGlobals.LongLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal LongDataContract(XmlDictionaryString name, XmlDictionaryString ns)
: base(typeof(long), name, ns)
{
}
internal override string WriteMethodName => "WriteLong";
internal override string ReadMethodName => "ReadElementContentAsLong";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteLong((long)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsLong()
: HandleReadValue(reader.ReadElementContentAsLong(), context);
}
}
internal class IntegerDataContract : LongDataContract
{
internal IntegerDataContract() : base(DictionaryGlobals.integerLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class PositiveIntegerDataContract : LongDataContract
{
internal PositiveIntegerDataContract() : base(DictionaryGlobals.positiveIntegerLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class NegativeIntegerDataContract : LongDataContract
{
internal NegativeIntegerDataContract() : base(DictionaryGlobals.negativeIntegerLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class NonPositiveIntegerDataContract : LongDataContract
{
internal NonPositiveIntegerDataContract() : base(DictionaryGlobals.nonPositiveIntegerLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class NonNegativeIntegerDataContract : LongDataContract
{
internal NonNegativeIntegerDataContract() : base(DictionaryGlobals.nonNegativeIntegerLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class UnsignedLongDataContract : PrimitiveDataContract
{
internal UnsignedLongDataContract()
: base(typeof(ulong), DictionaryGlobals.UnsignedLongLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteUnsignedLong";
internal override string ReadMethodName => "ReadElementContentAsUnsignedLong";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteUnsignedLong((ulong)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsUnsignedLong()
: HandleReadValue(reader.ReadElementContentAsUnsignedLong(), context);
}
}
internal class FloatDataContract : PrimitiveDataContract
{
internal FloatDataContract()
: base(typeof(float), DictionaryGlobals.FloatLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteFloat";
internal override string ReadMethodName => "ReadElementContentAsFloat";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteFloat((float)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsFloat()
: HandleReadValue(reader.ReadElementContentAsFloat(), context);
}
}
internal class DoubleDataContract : PrimitiveDataContract
{
internal DoubleDataContract()
: base(typeof(double), DictionaryGlobals.DoubleLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteDouble";
internal override string ReadMethodName => "ReadElementContentAsDouble";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteDouble((double)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsDouble()
: HandleReadValue(reader.ReadElementContentAsDouble(), context);
}
}
internal class DecimalDataContract : PrimitiveDataContract
{
internal DecimalDataContract()
: base(typeof(decimal), DictionaryGlobals.DecimalLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteDecimal";
internal override string ReadMethodName => "ReadElementContentAsDecimal";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteDecimal((decimal)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsDecimal()
: HandleReadValue(reader.ReadElementContentAsDecimal(), context);
}
}
internal class DateTimeDataContract : PrimitiveDataContract
{
internal DateTimeDataContract()
: base(typeof(DateTime), DictionaryGlobals.DateTimeLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteDateTime";
internal override string ReadMethodName => "ReadElementContentAsDateTime";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteDateTime((DateTime)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsDateTime()
: HandleReadValue(reader.ReadElementContentAsDateTime(), context);
}
}
internal class StringDataContract : PrimitiveDataContract
{
internal StringDataContract()
: this(DictionaryGlobals.StringLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal StringDataContract(XmlDictionaryString name, XmlDictionaryString ns)
: base(typeof(string), name, ns)
{
}
internal override string WriteMethodName => "WriteString";
internal override string ReadMethodName => "ReadElementContentAsString";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteString((string)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
if (context == null)
{
return TryReadNullAtTopLevel(reader) ? null : reader.ReadElementContentAsString();
}
else
{
return HandleReadValue(reader.ReadElementContentAsString(), context);
}
}
}
internal class TimeDataContract : StringDataContract
{
internal TimeDataContract() : base(DictionaryGlobals.timeLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class DateDataContract : StringDataContract
{
internal DateDataContract() : base(DictionaryGlobals.dateLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class HexBinaryDataContract : StringDataContract
{
internal HexBinaryDataContract() : base(DictionaryGlobals.hexBinaryLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class GYearMonthDataContract : StringDataContract
{
internal GYearMonthDataContract() : base(DictionaryGlobals.gYearMonthLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class GYearDataContract : StringDataContract
{
internal GYearDataContract() : base(DictionaryGlobals.gYearLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class GMonthDayDataContract : StringDataContract
{
internal GMonthDayDataContract() : base(DictionaryGlobals.gMonthDayLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class GDayDataContract : StringDataContract
{
internal GDayDataContract() : base(DictionaryGlobals.gDayLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class GMonthDataContract : StringDataContract
{
internal GMonthDataContract() : base(DictionaryGlobals.gMonthLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class NormalizedStringDataContract : StringDataContract
{
internal NormalizedStringDataContract() : base(DictionaryGlobals.normalizedStringLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class TokenDataContract : StringDataContract
{
internal TokenDataContract() : base(DictionaryGlobals.tokenLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class LanguageDataContract : StringDataContract
{
internal LanguageDataContract() : base(DictionaryGlobals.languageLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class NameDataContract : StringDataContract
{
internal NameDataContract() : base(DictionaryGlobals.NameLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class NCNameDataContract : StringDataContract
{
internal NCNameDataContract() : base(DictionaryGlobals.NCNameLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class IDDataContract : StringDataContract
{
internal IDDataContract() : base(DictionaryGlobals.XSDIDLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class IDREFDataContract : StringDataContract
{
internal IDREFDataContract() : base(DictionaryGlobals.IDREFLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class IDREFSDataContract : StringDataContract
{
internal IDREFSDataContract() : base(DictionaryGlobals.IDREFSLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class ENTITYDataContract : StringDataContract
{
internal ENTITYDataContract() : base(DictionaryGlobals.ENTITYLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class ENTITIESDataContract : StringDataContract
{
internal ENTITIESDataContract() : base(DictionaryGlobals.ENTITIESLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class NMTOKENDataContract : StringDataContract
{
internal NMTOKENDataContract() : base(DictionaryGlobals.NMTOKENLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class NMTOKENSDataContract : StringDataContract
{
internal NMTOKENSDataContract() : base(DictionaryGlobals.NMTOKENSLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class ByteArrayDataContract : PrimitiveDataContract
{
internal ByteArrayDataContract()
: base(typeof(byte[]), DictionaryGlobals.ByteArrayLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteBase64";
internal override string ReadMethodName => "ReadElementContentAsBase64";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteBase64((byte[])obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
if (context == null)
{
return TryReadNullAtTopLevel(reader) ? null : reader.ReadElementContentAsBase64();
}
else
{
return HandleReadValue(reader.ReadElementContentAsBase64(), context);
}
}
}
internal class ObjectDataContract : PrimitiveDataContract
{
internal ObjectDataContract()
: base(typeof(object), DictionaryGlobals.ObjectLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteAnyType";
internal override string ReadMethodName => "ReadElementContentAsAnyType";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
// write nothing
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
object obj;
if (reader.IsEmptyElement)
{
reader.Skip();
obj = new object();
}
else
{
string localName = reader.LocalName;
string ns = reader.NamespaceURI;
reader.Read();
try
{
reader.ReadEndElement();
obj = new object();
}
catch (XmlException xes)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.XmlForObjectCannotHaveContent, localName, ns), xes));
}
}
return (context == null) ? obj : HandleReadValue(obj, context);
}
internal override bool CanContainReferences => true;
internal override bool IsPrimitive => false;
}
internal class TimeSpanDataContract : PrimitiveDataContract
{
internal TimeSpanDataContract()
: this(DictionaryGlobals.TimeSpanLocalName, DictionaryGlobals.SerializationNamespace)
{
}
internal TimeSpanDataContract(XmlDictionaryString name, XmlDictionaryString ns)
: base(typeof(TimeSpan), name, ns)
{
}
internal override string WriteMethodName => "WriteTimeSpan";
internal override string ReadMethodName => "ReadElementContentAsTimeSpan";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteTimeSpan((TimeSpan)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsTimeSpan()
: HandleReadValue(reader.ReadElementContentAsTimeSpan(), context);
}
}
internal class XsDurationDataContract : TimeSpanDataContract
{
internal XsDurationDataContract() : base(DictionaryGlobals.TimeSpanLocalName, DictionaryGlobals.SchemaNamespace) { }
}
internal class GuidDataContract : PrimitiveDataContract
{
internal GuidDataContract()
: this(DictionaryGlobals.GuidLocalName, DictionaryGlobals.SerializationNamespace)
{
}
internal GuidDataContract(XmlDictionaryString name, XmlDictionaryString ns)
: base(typeof(Guid), name, ns)
{
}
internal override string WriteMethodName => "WriteGuid";
internal override string ReadMethodName => "ReadElementContentAsGuid";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteGuid((Guid)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
return (context == null) ? reader.ReadElementContentAsGuid()
: HandleReadValue(reader.ReadElementContentAsGuid(), context);
}
}
internal class AsmxGuidDataContract : GuidDataContract
{
internal AsmxGuidDataContract() : base(DictionaryGlobals.GuidLocalName, DictionaryGlobals.AsmxTypesNamespace) { }
}
internal class UriDataContract : PrimitiveDataContract
{
internal UriDataContract()
: base(typeof(Uri), DictionaryGlobals.UriLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteUri";
internal override string ReadMethodName => "ReadElementContentAsUri";
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteUri((Uri)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
if (context == null)
{
return TryReadNullAtTopLevel(reader) ? null : reader.ReadElementContentAsUri();
}
else
{
return HandleReadValue(reader.ReadElementContentAsUri(), context);
}
}
}
internal class QNameDataContract : PrimitiveDataContract
{
internal QNameDataContract()
: base(typeof(XmlQualifiedName), DictionaryGlobals.QNameLocalName, DictionaryGlobals.SchemaNamespace)
{
}
internal override string WriteMethodName => "WriteQName";
internal override string ReadMethodName => "ReadElementContentAsQName";
internal override bool IsPrimitive => false;
public override void WriteXmlValue(XmlWriterDelegator writer, object obj, XmlObjectSerializerWriteContext context)
{
writer.WriteQName((XmlQualifiedName)obj);
}
public override object ReadXmlValue(XmlReaderDelegator reader, XmlObjectSerializerReadContext context)
{
if (context == null)
{
return TryReadNullAtTopLevel(reader) ? null : reader.ReadElementContentAsQName();
}
else
{
return HandleReadValue(reader.ReadElementContentAsQName(), context);
}
}
internal override void WriteRootElement(XmlWriterDelegator writer, XmlDictionaryString name, XmlDictionaryString ns)
{
if (object.ReferenceEquals(ns, DictionaryGlobals.SerializationNamespace))
{
writer.WriteStartElement(Globals.SerPrefix, name, ns);
}
else if (ns != null && ns.Value != null && ns.Value.Length > 0)
{
writer.WriteStartElement(Globals.ElementPrefix, name, ns);
}
else
{
writer.WriteStartElement(name, ns);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,246 @@
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
namespace Compat.Runtime.Serialization
{
using SchemaObjectDictionary = Dictionary<XmlQualifiedName, SchemaObjectInfo>;
internal class SchemaObjectInfo
{
internal XmlSchemaType type;
internal XmlSchemaElement element;
internal XmlSchema schema;
internal List<XmlSchemaType> knownTypes;
internal SchemaObjectInfo(XmlSchemaType type, XmlSchemaElement element, XmlSchema schema, List<XmlSchemaType> knownTypes)
{
this.type = type;
this.element = element;
this.schema = schema;
this.knownTypes = knownTypes;
}
}
internal static class SchemaHelper
{
internal static bool NamespacesEqual(string ns1, string ns2)
{
if (ns1 == null || ns1.Length == 0)
{
return (ns2 == null || ns2.Length == 0);
}
else
{
return ns1 == ns2;
}
}
internal static XmlSchemaType GetSchemaType(XmlSchemaSet schemas, XmlQualifiedName typeQName, out XmlSchema outSchema)
{
outSchema = null;
ICollection currentSchemas = schemas.Schemas();
string ns = typeQName.Namespace;
foreach (XmlSchema schema in currentSchemas)
{
if (NamespacesEqual(ns, schema.TargetNamespace))
{
outSchema = schema;
foreach (XmlSchemaObject schemaObj in schema.Items)
{
XmlSchemaType schemaType = schemaObj as XmlSchemaType;
if (schemaType != null && schemaType.Name == typeQName.Name)
{
return schemaType;
}
}
}
}
return null;
}
internal static XmlSchemaType GetSchemaType(SchemaObjectDictionary schemaInfo, XmlQualifiedName typeName)
{
if (schemaInfo.TryGetValue(typeName, out SchemaObjectInfo schemaObjectInfo))
{
return schemaObjectInfo.type;
}
return null;
}
internal static XmlSchema GetSchemaWithType(SchemaObjectDictionary schemaInfo, XmlSchemaSet schemas, XmlQualifiedName typeName)
{
if (schemaInfo.TryGetValue(typeName, out SchemaObjectInfo schemaObjectInfo))
{
if (schemaObjectInfo.schema != null)
{
return schemaObjectInfo.schema;
}
}
ICollection currentSchemas = schemas.Schemas();
string ns = typeName.Namespace;
foreach (XmlSchema schema in currentSchemas)
{
if (NamespacesEqual(ns, schema.TargetNamespace))
{
return schema;
}
}
return null;
}
internal static XmlSchemaElement GetSchemaElement(XmlSchemaSet schemas, XmlQualifiedName elementQName, out XmlSchema outSchema)
{
outSchema = null;
ICollection currentSchemas = schemas.Schemas();
string ns = elementQName.Namespace;
foreach (XmlSchema schema in currentSchemas)
{
if (NamespacesEqual(ns, schema.TargetNamespace))
{
outSchema = schema;
foreach (XmlSchemaObject schemaObj in schema.Items)
{
XmlSchemaElement schemaElement = schemaObj as XmlSchemaElement;
if (schemaElement != null && schemaElement.Name == elementQName.Name)
{
return schemaElement;
}
}
}
}
return null;
}
internal static XmlSchemaElement GetSchemaElement(SchemaObjectDictionary schemaInfo, XmlQualifiedName elementName)
{
if (schemaInfo.TryGetValue(elementName, out SchemaObjectInfo schemaObjectInfo))
{
return schemaObjectInfo.element;
}
return null;
}
internal static XmlSchema GetSchema(string ns, XmlSchemaSet schemas)
{
if (ns == null) { ns = string.Empty; }
ICollection currentSchemas = schemas.Schemas();
foreach (XmlSchema schema in currentSchemas)
{
if ((schema.TargetNamespace == null && ns.Length == 0) || ns.Equals(schema.TargetNamespace))
{
return schema;
}
}
return CreateSchema(ns, schemas);
}
private static XmlSchema CreateSchema(string ns, XmlSchemaSet schemas)
{
XmlSchema schema = new XmlSchema
{
ElementFormDefault = XmlSchemaForm.Qualified
};
if (ns.Length > 0)
{
schema.TargetNamespace = ns;
schema.Namespaces.Add(Globals.TnsPrefix, ns);
}
schemas.Add(schema);
return schema;
}
internal static void AddElementForm(XmlSchemaElement element, XmlSchema schema)
{
if (schema.ElementFormDefault != XmlSchemaForm.Qualified)
{
element.Form = XmlSchemaForm.Qualified;
}
}
internal static void AddSchemaImport(string ns, XmlSchema schema)
{
if (SchemaHelper.NamespacesEqual(ns, schema.TargetNamespace) || SchemaHelper.NamespacesEqual(ns, Globals.SchemaNamespace) || SchemaHelper.NamespacesEqual(ns, Globals.SchemaInstanceNamespace))
{
return;
}
foreach (object item in schema.Includes)
{
if (item is XmlSchemaImport)
{
if (SchemaHelper.NamespacesEqual(ns, ((XmlSchemaImport)item).Namespace))
{
return;
}
}
}
XmlSchemaImport import = new XmlSchemaImport();
if (ns != null && ns.Length > 0)
{
import.Namespace = ns;
}
schema.Includes.Add(import);
}
internal static XmlSchema GetSchemaWithGlobalElementDeclaration(XmlSchemaElement element, XmlSchemaSet schemas)
{
ICollection currentSchemas = schemas.Schemas();
foreach (XmlSchema schema in currentSchemas)
{
foreach (XmlSchemaObject schemaObject in schema.Items)
{
XmlSchemaElement schemaElement = schemaObject as XmlSchemaElement;
if (schemaElement == null)
{
continue;
}
if (schemaElement == element)
{
return schema;
}
}
}
return null;
}
internal static XmlQualifiedName GetGlobalElementDeclaration(XmlSchemaSet schemas, XmlQualifiedName typeQName, out bool isNullable)
{
ICollection currentSchemas = schemas.Schemas();
string ns = typeQName.Namespace;
if (ns == null)
{
ns = string.Empty;
}
isNullable = false;
foreach (XmlSchema schema in currentSchemas)
{
foreach (XmlSchemaObject schemaObject in schema.Items)
{
XmlSchemaElement schemaElement = schemaObject as XmlSchemaElement;
if (schemaElement == null)
{
continue;
}
if (schemaElement.SchemaTypeName.Equals(typeQName))
{
isNullable = schemaElement.IsNillable;
return new XmlQualifiedName(schemaElement.Name, schema.TargetNamespace);
}
}
}
return null;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
using System;
using System.Xml;
namespace Compat.Runtime.Serialization
{
using DataContractDictionary = System.Collections.Generic.Dictionary<XmlQualifiedName, DataContract>;
internal struct ScopedKnownTypes
{
internal DataContractDictionary[] dataContractDictionaries;
private int count;
internal void Push(DataContractDictionary dataContractDictionary)
{
if (dataContractDictionaries == null)
{
dataContractDictionaries = new DataContractDictionary[4];
}
else if (count == dataContractDictionaries.Length)
{
Array.Resize<DataContractDictionary>(ref dataContractDictionaries, dataContractDictionaries.Length * 2);
}
dataContractDictionaries[count++] = dataContractDictionary;
}
internal void Pop()
{
count--;
}
internal DataContract GetDataContract(XmlQualifiedName qname)
{
for (int i = (count - 1); i >= 0; i--)
{
DataContractDictionary dataContractDictionary = dataContractDictionaries[i];
if (dataContractDictionary.TryGetValue(qname, out DataContract dataContract))
{
return dataContract;
}
}
return null;
}
}
}

View File

@@ -0,0 +1,8 @@
namespace Compat.Runtime.Serialization
{
internal enum SerializationMode
{
SharedContract,
SharedType,
}
}

View File

@@ -0,0 +1,33 @@
using System.Diagnostics;
namespace Compat.Runtime.Serialization
{
internal static class SerializationTrace
{
private static TraceSource _codeGen;
internal static SourceSwitch CodeGenerationSwitch => CodeGenerationTraceSource.Switch;
internal static void WriteInstruction(int lineNumber, string instruction)
{
CodeGenerationTraceSource.TraceInformation("{0:00000}: {1}", lineNumber, instruction);
}
internal static void TraceInstruction(string instruction)
{
CodeGenerationTraceSource.TraceEvent(TraceEventType.Verbose, 0, instruction);
}
private static TraceSource CodeGenerationTraceSource
{
get
{
if (_codeGen == null)
{
_codeGen = new TraceSource("E5.Runtime.Serialization.CodeGeneration");
}
return _codeGen;
}
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal sealed class SpecialTypeDataContract : DataContract
{
public SpecialTypeDataContract(Type type)
: base(new SpecialTypeDataContractCriticalHelper(type))
{
}
public SpecialTypeDataContract(Type type, XmlDictionaryString name, XmlDictionaryString ns)
: base(new SpecialTypeDataContractCriticalHelper(type, name, ns))
{
}
internal override bool IsBuiltInDataContract => true;
private class SpecialTypeDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
internal SpecialTypeDataContractCriticalHelper(Type type)
: base(type)
{
}
internal SpecialTypeDataContractCriticalHelper(Type type, XmlDictionaryString name, XmlDictionaryString ns)
: base(type)
{
SetDataContractName(name, ns);
}
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace Compat.Runtime.Serialization
{
internal sealed class SurrogateDataContract : DataContract
{
private readonly SurrogateDataContractCriticalHelper _helper;
internal SurrogateDataContract(Type type, ISerializationSurrogate serializationSurrogate)
: base(new SurrogateDataContractCriticalHelper(type, serializationSurrogate))
{
_helper = base.Helper as SurrogateDataContractCriticalHelper;
}
internal ISerializationSurrogate SerializationSurrogate => _helper.SerializationSurrogate;
public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
{
SerializationInfo serInfo = new SerializationInfo(UnderlyingType, XmlObjectSerializer.FormatterConverter, !context.UnsafeTypeForwardingEnabled);
SerializationSurrogateGetObjectData(obj, serInfo, context.GetStreamingContext());
context.WriteSerializationInfo(xmlWriter, UnderlyingType, serInfo);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private object SerializationSurrogateSetObjectData(object obj, SerializationInfo serInfo, StreamingContext context)
{
return SerializationSurrogate.SetObjectData(obj, serInfo, context, null);
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static object GetRealObject(IObjectReference obj, StreamingContext context)
{
return obj.GetRealObject(context);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private object GetUninitializedObject(Type objType)
{
return FormatterServices.GetUninitializedObject(objType);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void SerializationSurrogateGetObjectData(object obj, SerializationInfo serInfo, StreamingContext context)
{
SerializationSurrogate.GetObjectData(obj, serInfo, context);
}
public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
{
xmlReader.Read();
Type objType = UnderlyingType;
object obj = objType.IsArray ? Array.CreateInstance(objType.GetElementType(), 0) : GetUninitializedObject(objType);
context.AddNewObject(obj);
string objectId = context.GetObjectId();
SerializationInfo serInfo = context.ReadSerializationInfo(xmlReader, objType);
object newObj = SerializationSurrogateSetObjectData(obj, serInfo, context.GetStreamingContext());
if (newObj == null)
{
newObj = obj;
}
if (newObj is IDeserializationCallback)
{
((IDeserializationCallback)newObj).OnDeserialization(null);
}
if (newObj is IObjectReference)
{
newObj = GetRealObject((IObjectReference)newObj, context.GetStreamingContext());
}
context.ReplaceDeserializedObject(objectId, obj, newObj);
xmlReader.ReadEndElement();
return newObj;
}
private class SurrogateDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
private readonly ISerializationSurrogate _serializationSurrogate;
internal SurrogateDataContractCriticalHelper(Type type, ISerializationSurrogate serializationSurrogate)
: base(type)
{
_serializationSurrogate = serializationSurrogate;
DataContract.GetDefaultStableName(DataContract.GetClrTypeFullName(type), out string name, out string ns);
SetDataContractName(CreateQualifiedName(name, ns));
}
internal ISerializationSurrogate SerializationSurrogate => _serializationSurrogate;
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
namespace Compat.Runtime.Serialization
{
internal class TypeHandleRef
{
private RuntimeTypeHandle _value;
public TypeHandleRef()
{
}
public TypeHandleRef(RuntimeTypeHandle value)
{
_value = value;
}
public RuntimeTypeHandle Value
{
get => _value;
set => _value = value;
}
}
}

View File

@@ -0,0 +1,17 @@
using System.Collections.Generic;
namespace Compat.Runtime.Serialization
{
internal class TypeHandleRefEqualityComparer : IEqualityComparer<TypeHandleRef>
{
public bool Equals(TypeHandleRef x, TypeHandleRef y)
{
return x.Value.Equals(y.Value);
}
public int GetHashCode(TypeHandleRef obj)
{
return obj.Value.GetHashCode();
}
}
}

View File

@@ -0,0 +1,22 @@
namespace Compat.Runtime.Serialization
{
internal sealed class TypeInformation
{
private readonly string _fullTypeName;
private readonly string _assemblyString;
private readonly bool _hasTypeForwardedFrom;
internal TypeInformation(string fullTypeName, string assemblyString, bool hasTypeForwardedFrom)
{
_fullTypeName = fullTypeName;
_assemblyString = assemblyString;
_hasTypeForwardedFrom = hasTypeForwardedFrom;
}
internal string FullTypeName => _fullTypeName;
internal string AssemblyString => _assemblyString;
internal bool HasTypeForwardedFrom => _hasTypeForwardedFrom;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,370 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Security;
using System.Threading;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace Compat.Runtime.Serialization
{
using DataContractDictionary = Dictionary<XmlQualifiedName, DataContract>;
internal delegate IXmlSerializable CreateXmlSerializableDelegate();
internal sealed class XmlDataContract : DataContract
{
private readonly XmlDataContractCriticalHelper _helper;
internal XmlDataContract()
: base(new XmlDataContractCriticalHelper())
{
_helper = base.Helper as XmlDataContractCriticalHelper;
}
internal XmlDataContract(Type type)
: base(new XmlDataContractCriticalHelper(type))
{
_helper = base.Helper as XmlDataContractCriticalHelper;
}
internal override DataContractDictionary KnownDataContracts
{
get => _helper.KnownDataContracts;
set => _helper.KnownDataContracts = value;
}
internal XmlSchemaType XsdType
{
get => _helper.XsdType;
set => _helper.XsdType = value;
}
internal bool IsAnonymous => _helper.IsAnonymous;
internal override bool HasRoot
{
get => _helper.HasRoot;
set => _helper.HasRoot = value;
}
internal override XmlDictionaryString TopLevelElementName
{
get => _helper.TopLevelElementName;
set => _helper.TopLevelElementName = value;
}
internal override XmlDictionaryString TopLevelElementNamespace
{
get => _helper.TopLevelElementNamespace;
set => _helper.TopLevelElementNamespace = value;
}
internal bool IsTopLevelElementNullable
{
get => _helper.IsTopLevelElementNullable;
set => _helper.IsTopLevelElementNullable = value;
}
internal bool IsTypeDefinedOnImport
{
get => _helper.IsTypeDefinedOnImport;
set => _helper.IsTypeDefinedOnImport = value;
}
internal CreateXmlSerializableDelegate CreateXmlSerializableDelegate
{
get
{
if (_helper.CreateXmlSerializableDelegate == null)
{
lock (this)
{
if (_helper.CreateXmlSerializableDelegate == null)
{
CreateXmlSerializableDelegate tempCreateXmlSerializable = GenerateCreateXmlSerializableDelegate();
Thread.MemoryBarrier();
_helper.CreateXmlSerializableDelegate = tempCreateXmlSerializable;
}
}
}
return _helper.CreateXmlSerializableDelegate;
}
}
internal override bool CanContainReferences => false;
internal override bool IsBuiltInDataContract => UnderlyingType == Globals.TypeOfXmlElement || UnderlyingType == Globals.TypeOfXmlNodeArray;
private class XmlDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
private DataContractDictionary knownDataContracts;
private bool isKnownTypeAttributeChecked;
private XmlDictionaryString topLevelElementName;
private XmlDictionaryString topLevelElementNamespace;
private bool isTopLevelElementNullable;
private bool isTypeDefinedOnImport;
private XmlSchemaType xsdType;
private bool hasRoot;
private CreateXmlSerializableDelegate createXmlSerializable;
internal XmlDataContractCriticalHelper()
{
}
internal XmlDataContractCriticalHelper(Type type)
: base(type)
{
if (type.IsDefined(Globals.TypeOfDataContractAttribute, false))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.IXmlSerializableCannotHaveDataContract, DataContract.GetClrTypeFullName(type))));
}
if (type.IsDefined(Globals.TypeOfCollectionDataContractAttribute, false))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.IXmlSerializableCannotHaveCollectionDataContract, DataContract.GetClrTypeFullName(type))));
}
SchemaExporter.GetXmlTypeInfo(type, out XmlQualifiedName stableName, out XmlSchemaType xsdType, out bool hasRoot);
StableName = stableName;
XsdType = xsdType;
HasRoot = hasRoot;
XmlDictionary dictionary = new XmlDictionary();
Name = dictionary.Add(StableName.Name);
Namespace = dictionary.Add(StableName.Namespace);
object[] xmlRootAttributes = (UnderlyingType == null) ? null : UnderlyingType.GetCustomAttributes(Globals.TypeOfXmlRootAttribute, false);
if (xmlRootAttributes == null || xmlRootAttributes.Length == 0)
{
if (hasRoot)
{
topLevelElementName = Name;
topLevelElementNamespace = (StableName.Namespace == Globals.SchemaNamespace) ? DictionaryGlobals.EmptyString : Namespace;
isTopLevelElementNullable = true;
}
}
else
{
if (hasRoot)
{
XmlRootAttribute xmlRootAttribute = (XmlRootAttribute)xmlRootAttributes[0];
isTopLevelElementNullable = xmlRootAttribute.IsNullable;
string elementName = xmlRootAttribute.ElementName;
topLevelElementName = (elementName == null || elementName.Length == 0) ? Name : dictionary.Add(DataContract.EncodeLocalName(elementName));
string elementNs = xmlRootAttribute.Namespace;
topLevelElementNamespace = (elementNs == null || elementNs.Length == 0) ? DictionaryGlobals.EmptyString : dictionary.Add(elementNs);
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.IsAnyCannotHaveXmlRoot, DataContract.GetClrTypeFullName(UnderlyingType))));
}
}
}
internal override DataContractDictionary KnownDataContracts
{
get
{
if (!isKnownTypeAttributeChecked && UnderlyingType != null)
{
lock (this)
{
if (!isKnownTypeAttributeChecked)
{
knownDataContracts = DataContract.ImportKnownTypeAttributes(UnderlyingType);
Thread.MemoryBarrier();
isKnownTypeAttributeChecked = true;
}
}
}
return knownDataContracts;
}
set => knownDataContracts = value;
}
internal XmlSchemaType XsdType
{
get => xsdType;
set => xsdType = value;
}
internal bool IsAnonymous => xsdType != null;
internal override bool HasRoot
{
get => hasRoot;
set => hasRoot = value;
}
internal override XmlDictionaryString TopLevelElementName
{
get => topLevelElementName;
set => topLevelElementName = value;
}
internal override XmlDictionaryString TopLevelElementNamespace
{
get => topLevelElementNamespace;
set => topLevelElementNamespace = value;
}
internal bool IsTopLevelElementNullable
{
get => isTopLevelElementNullable;
set => isTopLevelElementNullable = value;
}
internal bool IsTypeDefinedOnImport
{
get => isTypeDefinedOnImport;
set => isTypeDefinedOnImport = value;
}
internal CreateXmlSerializableDelegate CreateXmlSerializableDelegate
{
get => createXmlSerializable;
set => createXmlSerializable = value;
}
}
private ConstructorInfo GetConstructor()
{
Type type = UnderlyingType;
if (type.IsValueType)
{
return null;
}
ConstructorInfo ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
if (ctor == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.IXmlSerializableMustHaveDefaultConstructor, DataContract.GetClrTypeFullName(type))));
}
return ctor;
}
internal void SetTopLevelElementName(XmlQualifiedName elementName)
{
if (elementName != null)
{
XmlDictionary dictionary = new XmlDictionary();
TopLevelElementName = dictionary.Add(elementName.Name);
TopLevelElementNamespace = dictionary.Add(elementName.Namespace);
}
}
internal CreateXmlSerializableDelegate GenerateCreateXmlSerializableDelegate()
{
Type type = UnderlyingType;
CodeGenerator ilg = new CodeGenerator();
bool memberAccessFlag = RequiresMemberAccessForCreate(null);
ilg.BeginMethod("Create" + DataContract.GetClrTypeFullName(type), typeof(CreateXmlSerializableDelegate), memberAccessFlag);
if (type.IsValueType)
{
System.Reflection.Emit.LocalBuilder local = ilg.DeclareLocal(type, type.Name + "Value");
ilg.Ldloca(local);
ilg.InitObj(type);
ilg.Ldloc(local);
}
else
{
ilg.New(GetConstructor());
}
ilg.ConvertValue(UnderlyingType, Globals.TypeOfIXmlSerializable);
ilg.Ret();
return (CreateXmlSerializableDelegate)ilg.EndMethod();
}
private bool RequiresMemberAccessForCreate(SecurityException securityException)
{
if (!IsTypeVisible(UnderlyingType))
{
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(SR.Format(SR.PartialTrustIXmlSerializableTypeNotPublic, DataContract.GetClrTypeFullName(UnderlyingType)),
securityException));
}
return true;
}
if (ConstructorRequiresMemberAccess(GetConstructor()))
{
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(SR.Format(SR.PartialTrustIXmlSerialzableNoPublicConstructor, DataContract.GetClrTypeFullName(UnderlyingType)),
securityException));
}
return true;
}
return false;
}
internal override bool Equals(object other, Dictionary<DataContractPairKey, object> checkedContracts)
{
if (IsEqualOrChecked(other, checkedContracts))
{
return true;
}
XmlDataContract dataContract = other as XmlDataContract;
if (dataContract != null)
{
if (HasRoot != dataContract.HasRoot)
{
return false;
}
if (IsAnonymous)
{
return dataContract.IsAnonymous;
}
else
{
return (StableName.Name == dataContract.StableName.Name && StableName.Namespace == dataContract.StableName.Namespace);
}
}
return false;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
{
if (context == null)
{
XmlObjectSerializerWriteContext.WriteRootIXmlSerializable(xmlWriter, obj);
}
else
{
context.WriteIXmlSerializable(xmlWriter, obj);
}
}
public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
{
object o;
if (context == null)
{
o = XmlObjectSerializerReadContext.ReadRootIXmlSerializable(xmlReader, this, true /*isMemberType*/);
}
else
{
o = context.ReadIXmlSerializable(xmlReader, this, true /*isMemberType*/);
context.AddNewObject(o);
}
xmlReader.ReadEndElement();
return o;
}
}
}

View File

@@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal class XmlDataNode : DataNode<object>
{
private IList<XmlAttribute> _xmlAttributes;
private IList<XmlNode> _xmlChildNodes;
private XmlDocument _ownerDocument;
internal XmlDataNode()
{
dataType = Globals.TypeOfXmlDataNode;
}
internal IList<XmlAttribute> XmlAttributes
{
get => _xmlAttributes;
set => _xmlAttributes = value;
}
internal IList<XmlNode> XmlChildNodes
{
get => _xmlChildNodes;
set => _xmlChildNodes = value;
}
internal XmlDocument OwnerDocument
{
get => _ownerDocument;
set => _ownerDocument = value;
}
public override void Clear()
{
base.Clear();
_xmlAttributes = null;
_xmlChildNodes = null;
_ownerDocument = null;
}
}
}

View File

@@ -0,0 +1,902 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal delegate object XmlFormatClassReaderDelegate(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces);
internal delegate object XmlFormatCollectionReaderDelegate(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract);
internal delegate void XmlFormatGetOnlyCollectionReaderDelegate(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract);
internal sealed class XmlFormatReaderGenerator
{
private readonly CriticalHelper _helper;
public XmlFormatReaderGenerator()
{
_helper = new CriticalHelper();
}
public XmlFormatClassReaderDelegate GenerateClassReader(ClassDataContract classContract)
{
return _helper.GenerateClassReader(classContract);
}
public XmlFormatCollectionReaderDelegate GenerateCollectionReader(CollectionDataContract collectionContract)
{
return _helper.GenerateCollectionReader(collectionContract);
}
public XmlFormatGetOnlyCollectionReaderDelegate GenerateGetOnlyCollectionReader(CollectionDataContract collectionContract)
{
return _helper.GenerateGetOnlyCollectionReader(collectionContract);
}
private class CriticalHelper
{
private CodeGenerator ilg;
private LocalBuilder objectLocal;
private Type objectType;
private ArgBuilder xmlReaderArg;
private ArgBuilder contextArg;
private ArgBuilder memberNamesArg;
private ArgBuilder memberNamespacesArg;
private ArgBuilder collectionContractArg;
public XmlFormatClassReaderDelegate GenerateClassReader(ClassDataContract classContract)
{
ilg = new CodeGenerator();
bool memberAccessFlag = classContract.RequiresMemberAccessForRead(null);
ilg.BeginMethod("Read" + classContract.StableName.Name + "FromXml", Globals.TypeOfXmlFormatClassReaderDelegate, memberAccessFlag);
InitArgs();
CreateObject(classContract);
ilg.Call(contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, objectLocal);
InvokeOnDeserializing(classContract);
LocalBuilder objectId = null;
if (HasFactoryMethod(classContract))
{
objectId = ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead");
ilg.Call(contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod);
ilg.Stloc(objectId);
}
if (classContract.IsISerializable)
{
ReadISerializable(classContract);
}
else
{
ReadClass(classContract);
}
bool isFactoryType = InvokeFactoryMethod(classContract, objectId);
if (Globals.TypeOfIDeserializationCallback.IsAssignableFrom(classContract.UnderlyingType))
{
ilg.Call(objectLocal, XmlFormatGeneratorStatics.OnDeserializationMethod, null);
}
InvokeOnDeserialized(classContract);
if (objectId == null || !isFactoryType)
{
ilg.Load(objectLocal);
// 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)
{
ilg.ConvertValue(objectLocal.LocalType, Globals.TypeOfDateTimeOffsetAdapter);
ilg.Call(XmlFormatGeneratorStatics.GetDateTimeOffsetMethod);
ilg.ConvertValue(Globals.TypeOfDateTimeOffset, ilg.CurrentMethod.ReturnType);
}
else
{
ilg.ConvertValue(objectLocal.LocalType, ilg.CurrentMethod.ReturnType);
}
}
return (XmlFormatClassReaderDelegate)ilg.EndMethod();
}
public XmlFormatCollectionReaderDelegate GenerateCollectionReader(CollectionDataContract collectionContract)
{
ilg = GenerateCollectionReaderHelper(collectionContract, false /*isGetOnlyCollection*/);
ReadCollection(collectionContract);
ilg.Load(objectLocal);
ilg.ConvertValue(objectLocal.LocalType, ilg.CurrentMethod.ReturnType);
return (XmlFormatCollectionReaderDelegate)ilg.EndMethod();
}
public XmlFormatGetOnlyCollectionReaderDelegate GenerateGetOnlyCollectionReader(CollectionDataContract collectionContract)
{
ilg = GenerateCollectionReaderHelper(collectionContract, true /*isGetOnlyCollection*/);
ReadGetOnlyCollection(collectionContract);
return (XmlFormatGetOnlyCollectionReaderDelegate)ilg.EndMethod();
}
private CodeGenerator GenerateCollectionReaderHelper(CollectionDataContract collectionContract, bool isGetOnlyCollection)
{
ilg = new CodeGenerator();
bool memberAccessFlag = collectionContract.RequiresMemberAccessForRead(null);
if (isGetOnlyCollection)
{
ilg.BeginMethod("Read" + collectionContract.StableName.Name + "FromXml" + "IsGetOnly", Globals.TypeOfXmlFormatGetOnlyCollectionReaderDelegate, memberAccessFlag);
}
else
{
ilg.BeginMethod("Read" + collectionContract.StableName.Name + "FromXml" + string.Empty, Globals.TypeOfXmlFormatCollectionReaderDelegate, memberAccessFlag);
}
InitArgs();
collectionContractArg = ilg.GetArg(4);
return ilg;
}
private void InitArgs()
{
xmlReaderArg = ilg.GetArg(0);
contextArg = ilg.GetArg(1);
memberNamesArg = ilg.GetArg(2);
memberNamespacesArg = ilg.GetArg(3);
}
private void CreateObject(ClassDataContract classContract)
{
Type type = objectType = classContract.UnderlyingType;
if (type.IsValueType && !classContract.IsNonAttributedType)
{
type = Globals.TypeOfValueType;
}
objectLocal = ilg.DeclareLocal(type, "objectDeserialized");
if (classContract.UnderlyingType == Globals.TypeOfDBNull)
{
ilg.LoadMember(Globals.TypeOfDBNull.GetField("Value"));
ilg.Stloc(objectLocal);
}
else if (classContract.IsNonAttributedType)
{
if (type.IsValueType)
{
ilg.Ldloca(objectLocal);
ilg.InitObj(type);
}
else
{
ilg.New(classContract.GetNonAttributedTypeConstructor());
ilg.Stloc(objectLocal);
}
}
else
{
ilg.Call(null, XmlFormatGeneratorStatics.GetUninitializedObjectMethod, DataContract.GetIdForInitialization(classContract));
ilg.ConvertValue(Globals.TypeOfObject, type);
ilg.Stloc(objectLocal);
}
}
private void InvokeOnDeserializing(ClassDataContract classContract)
{
if (classContract.BaseContract != null)
{
InvokeOnDeserializing(classContract.BaseContract);
}
if (classContract.OnDeserializing != null)
{
ilg.LoadAddress(objectLocal);
ilg.ConvertAddress(objectLocal.LocalType, objectType);
ilg.Load(contextArg);
ilg.LoadMember(XmlFormatGeneratorStatics.GetStreamingContextMethod);
ilg.Call(classContract.OnDeserializing);
}
}
private void InvokeOnDeserialized(ClassDataContract classContract)
{
if (classContract.BaseContract != null)
{
InvokeOnDeserialized(classContract.BaseContract);
}
if (classContract.OnDeserialized != null)
{
ilg.LoadAddress(objectLocal);
ilg.ConvertAddress(objectLocal.LocalType, objectType);
ilg.Load(contextArg);
ilg.LoadMember(XmlFormatGeneratorStatics.GetStreamingContextMethod);
ilg.Call(classContract.OnDeserialized);
}
}
private bool HasFactoryMethod(ClassDataContract classContract)
{
return Globals.TypeOfIObjectReference.IsAssignableFrom(classContract.UnderlyingType);
}
private bool InvokeFactoryMethod(ClassDataContract classContract, LocalBuilder objectId)
{
if (HasFactoryMethod(classContract))
{
ilg.Load(contextArg);
ilg.LoadAddress(objectLocal);
ilg.ConvertAddress(objectLocal.LocalType, Globals.TypeOfIObjectReference);
ilg.Load(objectId);
ilg.Call(XmlFormatGeneratorStatics.GetRealObjectMethod);
ilg.ConvertValue(Globals.TypeOfObject, ilg.CurrentMethod.ReturnType);
return true;
}
return false;
}
private void ReadClass(ClassDataContract classContract)
{
if (classContract.HasExtensionData)
{
LocalBuilder extensionDataLocal = ilg.DeclareLocal(Globals.TypeOfExtensionDataObject, "extensionData");
ilg.New(XmlFormatGeneratorStatics.ExtensionDataObjectCtor);
ilg.Store(extensionDataLocal);
ReadMembers(classContract, extensionDataLocal);
ClassDataContract currentContract = classContract;
while (currentContract != null)
{
MethodInfo extensionDataSetMethod = currentContract.ExtensionDataSetMethod;
if (extensionDataSetMethod != null)
{
ilg.Call(objectLocal, extensionDataSetMethod, extensionDataLocal);
}
currentContract = currentContract.BaseContract;
}
}
else
{
ReadMembers(classContract, null /*extensionDataLocal*/);
}
}
private void ReadMembers(ClassDataContract classContract, LocalBuilder extensionDataLocal)
{
int memberCount = classContract.MemberNames.Length;
ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, memberCount);
LocalBuilder memberIndexLocal = ilg.DeclareLocal(Globals.TypeOfInt, "memberIndex", -1);
bool[] requiredMembers = GetRequiredMembers(classContract, out int firstRequiredMember);
bool hasRequiredMembers = (firstRequiredMember < memberCount);
LocalBuilder requiredIndexLocal = hasRequiredMembers ? ilg.DeclareLocal(Globals.TypeOfInt, "requiredIndex", firstRequiredMember) : null;
object forReadElements = ilg.For(null, null, null);
ilg.Call(null, XmlFormatGeneratorStatics.MoveToNextElementMethod, xmlReaderArg);
ilg.IfFalseBreak(forReadElements);
if (hasRequiredMembers)
{
ilg.Call(contextArg, XmlFormatGeneratorStatics.GetMemberIndexWithRequiredMembersMethod, xmlReaderArg, memberNamesArg, memberNamespacesArg, memberIndexLocal, requiredIndexLocal, extensionDataLocal);
}
else
{
ilg.Call(contextArg, XmlFormatGeneratorStatics.GetMemberIndexMethod, xmlReaderArg, memberNamesArg, memberNamespacesArg, memberIndexLocal, extensionDataLocal);
}
if (memberCount > 0)
{
Label[] memberLabels = ilg.Switch(memberCount);
ReadMembers(classContract, requiredMembers, memberLabels, memberIndexLocal, requiredIndexLocal);
ilg.EndSwitch();
}
else
{
ilg.Pop();
}
ilg.EndFor();
if (hasRequiredMembers)
{
ilg.If(requiredIndexLocal, Cmp.LessThan, memberCount);
ilg.Call(null, XmlFormatGeneratorStatics.ThrowRequiredMemberMissingExceptionMethod, xmlReaderArg, memberIndexLocal, requiredIndexLocal, memberNamesArg);
ilg.EndIf();
}
}
private int ReadMembers(ClassDataContract classContract, bool[] requiredMembers, Label[] memberLabels, LocalBuilder memberIndexLocal, LocalBuilder requiredIndexLocal)
{
int memberCount = (classContract.BaseContract == null) ? 0 : ReadMembers(classContract.BaseContract, requiredMembers,
memberLabels, memberIndexLocal, requiredIndexLocal);
for (int i = 0; i < classContract.Members.Count; i++, memberCount++)
{
DataMember dataMember = classContract.Members[i];
Type memberType = dataMember.MemberType;
ilg.Case(memberLabels[memberCount], dataMember.Name);
if (dataMember.IsRequired)
{
int nextRequiredIndex = memberCount + 1;
for (; nextRequiredIndex < requiredMembers.Length; nextRequiredIndex++)
{
if (requiredMembers[nextRequiredIndex])
{
break;
}
}
ilg.Set(requiredIndexLocal, nextRequiredIndex);
}
LocalBuilder value = null;
if (dataMember.IsGetOnlyCollection)
{
ilg.LoadAddress(objectLocal);
ilg.LoadMember(dataMember.MemberInfo);
value = ilg.DeclareLocal(memberType, dataMember.Name + "Value");
ilg.Stloc(value);
ilg.Call(contextArg, XmlFormatGeneratorStatics.StoreCollectionMemberInfoMethod, value);
ReadValue(memberType, dataMember.Name, classContract.StableName.Namespace);
}
else
{
value = ReadValue(memberType, dataMember.Name, classContract.StableName.Namespace);
ilg.LoadAddress(objectLocal);
ilg.ConvertAddress(objectLocal.LocalType, objectType);
ilg.Ldloc(value);
ilg.StoreMember(dataMember.MemberInfo);
}
ilg.Set(memberIndexLocal, memberCount);
ilg.EndCase();
}
return memberCount;
}
private 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;
}
private 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;
}
private void ReadISerializable(ClassDataContract classContract)
{
ConstructorInfo ctor = classContract.GetISerializableConstructor();
ilg.LoadAddress(objectLocal);
ilg.ConvertAddress(objectLocal.LocalType, objectType);
ilg.Call(contextArg, XmlFormatGeneratorStatics.ReadSerializationInfoMethod, xmlReaderArg, classContract.UnderlyingType);
ilg.Load(contextArg);
ilg.LoadMember(XmlFormatGeneratorStatics.GetStreamingContextMethod);
ilg.Call(ctor);
}
private LocalBuilder ReadValue(Type type, string name, string ns)
{
LocalBuilder value = ilg.DeclareLocal(type, "valueRead");
LocalBuilder nullableValue = null;
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)
{
LocalBuilder objectId = ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead");
ilg.Call(contextArg, XmlFormatGeneratorStatics.ReadAttributesMethod, xmlReaderArg);
ilg.Call(contextArg, XmlFormatGeneratorStatics.ReadIfNullOrRefMethod, xmlReaderArg, type, DataContract.IsTypeSerializable(type));
ilg.Stloc(objectId);
// Deserialize null
ilg.If(objectId, Cmp.EqualTo, Globals.NullObjectId);
if (nullables != 0)
{
ilg.LoadAddress(value);
ilg.InitObj(value.LocalType);
}
else if (type.IsValueType)
{
ThrowValidationException(SR.Format(SR.ValueTypeCannotBeNull, DataContract.GetClrTypeFullName(type)));
}
else
{
ilg.Load(null);
ilg.Stloc(value);
}
// Deserialize value
// Compare against Globals.NewObjectId, which is set to string.Empty
ilg.ElseIfIsEmptyString(objectId);
ilg.Call(contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod);
ilg.Stloc(objectId);
if (type.IsValueType)
{
ilg.IfNotIsEmptyString(objectId);
ThrowValidationException(SR.Format(SR.ValueTypeCannotHaveId, DataContract.GetClrTypeFullName(type)));
ilg.EndIf();
}
if (nullables != 0)
{
nullableValue = value;
value = ilg.DeclareLocal(type, "innerValueRead");
}
if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject)
{
ilg.Call(xmlReaderArg, primitiveContract.XmlFormatReaderMethod);
ilg.Stloc(value);
if (!type.IsValueType)
{
ilg.Call(contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, value);
}
}
else
{
InternalDeserialize(value, type, name, ns);
}
// Deserialize ref
ilg.Else();
if (type.IsValueType)
{
ThrowValidationException(SR.Format(SR.ValueTypeCannotHaveRef, DataContract.GetClrTypeFullName(type)));
}
else
{
ilg.Call(contextArg, XmlFormatGeneratorStatics.GetExistingObjectMethod, objectId, type, name, ns);
ilg.ConvertValue(Globals.TypeOfObject, type);
ilg.Stloc(value);
}
ilg.EndIf();
if (nullableValue != null)
{
ilg.If(objectId, Cmp.NotEqualTo, Globals.NullObjectId);
WrapNullableObject(value, nullableValue, nullables);
ilg.EndIf();
value = nullableValue;
}
}
else
{
InternalDeserialize(value, type, name, ns);
}
return value;
}
private void InternalDeserialize(LocalBuilder value, Type type, string name, string ns)
{
ilg.Load(contextArg);
ilg.Load(xmlReaderArg);
Type declaredType = type.IsPointer ? Globals.TypeOfReflectionPointer : type;
ilg.Load(DataContract.GetId(declaredType.TypeHandle));
ilg.Ldtoken(declaredType);
ilg.Load(name);
ilg.Load(ns);
ilg.Call(XmlFormatGeneratorStatics.InternalDeserializeMethod);
if (type.IsPointer)
{
ilg.Call(XmlFormatGeneratorStatics.UnboxPointer);
}
else
{
ilg.ConvertValue(Globals.TypeOfObject, type);
}
ilg.Stloc(value);
}
private void WrapNullableObject(LocalBuilder innerValue, LocalBuilder outerValue, int nullables)
{
Type innerType = innerValue.LocalType, outerType = outerValue.LocalType;
ilg.LoadAddress(outerValue);
ilg.Load(innerValue);
for (int i = 1; i < nullables; i++)
{
Type type = Globals.TypeOfNullable.MakeGenericType(innerType);
ilg.New(type.GetConstructor(new Type[] { innerType }));
innerType = type;
}
ilg.Call(outerType.GetConstructor(new Type[] { innerType }));
}
private 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;
objectLocal = ilg.DeclareLocal(type, "objectDeserialized");
if (!isArray)
{
if (type.IsValueType)
{
ilg.Ldloca(objectLocal);
ilg.InitObj(type);
}
else
{
ilg.New(constructor);
ilg.Stloc(objectLocal);
ilg.Call(contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, objectLocal);
}
}
LocalBuilder size = ilg.DeclareLocal(Globals.TypeOfInt, "arraySize");
ilg.Call(contextArg, XmlFormatGeneratorStatics.GetArraySizeMethod);
ilg.Stloc(size);
LocalBuilder objectId = ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead");
ilg.Call(contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod);
ilg.Stloc(objectId);
bool canReadPrimitiveArray = false;
if (isArray && TryReadPrimitiveArray(type, itemType, size))
{
canReadPrimitiveArray = true;
ilg.IfNot();
}
ilg.If(size, Cmp.EqualTo, -1);
LocalBuilder growingCollection = null;
if (isArray)
{
growingCollection = ilg.DeclareLocal(type, "growingCollection");
ilg.NewArray(itemType, 32);
ilg.Stloc(growingCollection);
}
LocalBuilder i = ilg.DeclareLocal(Globals.TypeOfInt, "i");
object forLoop = ilg.For(i, 0, int.MaxValue);
IsStartElement(memberNamesArg, memberNamespacesArg);
ilg.If();
ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1);
LocalBuilder value = ReadCollectionItem(collectionContract, itemType, itemName, itemNs);
if (isArray)
{
MethodInfo ensureArraySizeMethod = XmlFormatGeneratorStatics.EnsureArraySizeMethod.MakeGenericMethod(itemType);
ilg.Call(null, ensureArraySizeMethod, growingCollection, i);
ilg.Stloc(growingCollection);
ilg.StoreArrayElement(growingCollection, i, value);
}
else
{
StoreCollectionValue(objectLocal, value, collectionContract);
}
ilg.Else();
IsEndElement();
ilg.If();
ilg.Break(forLoop);
ilg.Else();
HandleUnexpectedItemInCollection(i);
ilg.EndIf();
ilg.EndIf();
ilg.EndFor();
if (isArray)
{
MethodInfo trimArraySizeMethod = XmlFormatGeneratorStatics.TrimArraySizeMethod.MakeGenericMethod(itemType);
ilg.Call(null, trimArraySizeMethod, growingCollection, i);
ilg.Stloc(objectLocal);
ilg.Call(contextArg, XmlFormatGeneratorStatics.AddNewObjectWithIdMethod, objectId, objectLocal);
}
ilg.Else();
ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, size);
if (isArray)
{
ilg.NewArray(itemType, size);
ilg.Stloc(objectLocal);
ilg.Call(contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, objectLocal);
}
LocalBuilder j = ilg.DeclareLocal(Globals.TypeOfInt, "j");
ilg.For(j, 0, size);
IsStartElement(memberNamesArg, memberNamespacesArg);
ilg.If();
LocalBuilder itemValue = ReadCollectionItem(collectionContract, itemType, itemName, itemNs);
if (isArray)
{
ilg.StoreArrayElement(objectLocal, j, itemValue);
}
else
{
StoreCollectionValue(objectLocal, itemValue, collectionContract);
}
ilg.Else();
HandleUnexpectedItemInCollection(j);
ilg.EndIf();
ilg.EndFor();
ilg.Call(contextArg, XmlFormatGeneratorStatics.CheckEndOfArrayMethod, xmlReaderArg, size, memberNamesArg, memberNamespacesArg);
ilg.EndIf();
if (canReadPrimitiveArray)
{
ilg.Else();
ilg.Call(contextArg, XmlFormatGeneratorStatics.AddNewObjectWithIdMethod, objectId, objectLocal);
ilg.EndIf();
}
}
private 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 = ilg.DeclareLocal(type, "objectDeserialized");
ilg.Load(contextArg);
ilg.LoadMember(XmlFormatGeneratorStatics.GetCollectionMemberMethod);
ilg.ConvertValue(Globals.TypeOfObject, type);
ilg.Stloc(objectLocal);
//check that items are actually going to be deserialized into the collection
IsStartElement(memberNamesArg, memberNamespacesArg);
ilg.If();
ilg.If(objectLocal, Cmp.EqualTo, null);
ilg.Call(null, XmlFormatGeneratorStatics.ThrowNullValueReturnedForGetOnlyCollectionExceptionMethod, type);
ilg.Else();
LocalBuilder size = ilg.DeclareLocal(Globals.TypeOfInt, "arraySize");
if (isArray)
{
ilg.Load(objectLocal);
ilg.Call(XmlFormatGeneratorStatics.GetArrayLengthMethod);
ilg.Stloc(size);
}
ilg.Call(contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, objectLocal);
LocalBuilder i = ilg.DeclareLocal(Globals.TypeOfInt, "i");
object forLoop = ilg.For(i, 0, int.MaxValue);
IsStartElement(memberNamesArg, memberNamespacesArg);
ilg.If();
ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1);
LocalBuilder value = ReadCollectionItem(collectionContract, itemType, itemName, itemNs);
if (isArray)
{
ilg.If(size, Cmp.EqualTo, i);
ilg.Call(null, XmlFormatGeneratorStatics.ThrowArrayExceededSizeExceptionMethod, size, type);
ilg.Else();
ilg.StoreArrayElement(objectLocal, i, value);
ilg.EndIf();
}
else
{
StoreCollectionValue(objectLocal, value, collectionContract);
}
ilg.Else();
IsEndElement();
ilg.If();
ilg.Break(forLoop);
ilg.Else();
HandleUnexpectedItemInCollection(i);
ilg.EndIf();
ilg.EndIf();
ilg.EndFor();
ilg.Call(contextArg, XmlFormatGeneratorStatics.CheckEndOfArrayMethod, xmlReaderArg, size, memberNamesArg, memberNamespacesArg);
ilg.EndIf();
ilg.EndIf();
}
private bool TryReadPrimitiveArray(Type type, Type itemType, LocalBuilder size)
{
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)
{
ilg.Load(xmlReaderArg);
ilg.Load(contextArg);
ilg.Load(memberNamesArg);
ilg.Load(memberNamespacesArg);
ilg.Load(size);
ilg.Ldloca(objectLocal);
ilg.Call(typeof(XmlReaderDelegator).GetMethod(readArrayMethod, Globals.ScanAllMembers));
return true;
}
return false;
}
private LocalBuilder ReadCollectionItem(CollectionDataContract collectionContract, Type itemType, string itemName, string itemNs)
{
if (collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary)
{
ilg.Call(contextArg, XmlFormatGeneratorStatics.ResetAttributesMethod);
LocalBuilder value = ilg.DeclareLocal(itemType, "valueRead");
ilg.Load(collectionContractArg);
ilg.Call(XmlFormatGeneratorStatics.GetItemContractMethod);
ilg.Load(xmlReaderArg);
ilg.Load(contextArg);
ilg.Call(XmlFormatGeneratorStatics.ReadXmlValueMethod);
ilg.ConvertValue(Globals.TypeOfObject, itemType);
ilg.Stloc(value);
return value;
}
else
{
return ReadValue(itemType, itemName, itemNs);
}
}
private void StoreCollectionValue(LocalBuilder collection, LocalBuilder value, CollectionDataContract collectionContract)
{
if (collectionContract.Kind == CollectionKind.GenericDictionary || collectionContract.Kind == CollectionKind.Dictionary)
{
ClassDataContract keyValuePairContract = DataContract.GetDataContract(value.LocalType) as ClassDataContract;
if (keyValuePairContract == null)
{
Fx.Assert("Failed to create contract for KeyValuePair type");
}
DataMember keyMember = keyValuePairContract.Members[0];
DataMember valueMember = keyValuePairContract.Members[1];
LocalBuilder pairKey = ilg.DeclareLocal(keyMember.MemberType, keyMember.Name);
LocalBuilder pairValue = ilg.DeclareLocal(valueMember.MemberType, valueMember.Name);
ilg.LoadAddress(value);
ilg.LoadMember(keyMember.MemberInfo);
ilg.Stloc(pairKey);
ilg.LoadAddress(value);
ilg.LoadMember(valueMember.MemberInfo);
ilg.Stloc(pairValue);
ilg.Call(collection, collectionContract.AddMethod, pairKey, pairValue);
if (collectionContract.AddMethod.ReturnType != Globals.TypeOfVoid)
{
ilg.Pop();
}
}
else
{
ilg.Call(collection, collectionContract.AddMethod, value);
if (collectionContract.AddMethod.ReturnType != Globals.TypeOfVoid)
{
ilg.Pop();
}
}
}
private void HandleUnexpectedItemInCollection(LocalBuilder iterator)
{
IsStartElement();
ilg.If();
ilg.Call(contextArg, XmlFormatGeneratorStatics.SkipUnknownElementMethod, xmlReaderArg);
ilg.Dec(iterator);
ilg.Else();
ThrowUnexpectedStateException(XmlNodeType.Element);
ilg.EndIf();
}
private void IsStartElement(ArgBuilder nameArg, ArgBuilder nsArg)
{
ilg.Call(xmlReaderArg, XmlFormatGeneratorStatics.IsStartElementMethod2, nameArg, nsArg);
}
private void IsStartElement()
{
ilg.Call(xmlReaderArg, XmlFormatGeneratorStatics.IsStartElementMethod0);
}
private void IsEndElement()
{
ilg.Load(xmlReaderArg);
ilg.LoadMember(XmlFormatGeneratorStatics.NodeTypeProperty);
ilg.Load(XmlNodeType.EndElement);
ilg.Ceq();
}
private void ThrowUnexpectedStateException(XmlNodeType expectedState)
{
ilg.Call(null, XmlFormatGeneratorStatics.CreateUnexpectedStateExceptionMethod, expectedState, xmlReaderArg);
ilg.Throw();
}
private void ThrowValidationException(string msg, params object[] values)
{
if (values != null && values.Length > 0)
{
ilg.CallStringFormat(msg, values);
}
else
{
ilg.Load(msg);
}
ThrowValidationException();
}
private void ThrowValidationException()
{
ilg.New(XmlFormatGeneratorStatics.SerializationExceptionCtor);
ilg.Throw();
}
}
internal static object UnsafeGetUninitializedObject(int id)
{
return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(DataContract.GetDataContractForInitialization(id).TypeForInitialization);
}
}
}

View File

@@ -0,0 +1,743 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Security;
using System.Security.Permissions;
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal delegate void XmlFormatClassWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, ClassDataContract dataContract);
internal delegate void XmlFormatCollectionWriterDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, CollectionDataContract dataContract);
internal sealed class XmlFormatWriterGenerator
{
CriticalHelper _helper;
public XmlFormatWriterGenerator()
{
_helper = new CriticalHelper();
}
internal XmlFormatClassWriterDelegate GenerateClassWriter(ClassDataContract classContract)
{
return _helper.GenerateClassWriter(classContract);
}
internal XmlFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract)
{
return _helper.GenerateCollectionWriter(collectionContract);
}
class CriticalHelper
{
CodeGenerator ilg;
ArgBuilder xmlWriterArg;
ArgBuilder contextArg;
ArgBuilder dataContractArg;
LocalBuilder objectLocal;
// Used for classes
LocalBuilder contractNamespacesLocal;
LocalBuilder memberNamesLocal;
LocalBuilder childElementNamespacesLocal;
int typeIndex = 1;
int childElementIndex = 0;
internal XmlFormatClassWriterDelegate GenerateClassWriter(ClassDataContract classContract)
{
ilg = new CodeGenerator();
bool memberAccessFlag = classContract.RequiresMemberAccessForWrite(null);
ilg.BeginMethod("Write" + classContract.StableName.Name + "ToXml", Globals.TypeOfXmlFormatClassWriterDelegate, memberAccessFlag);
InitArgs(classContract.UnderlyingType);
if (classContract.IsReadOnlyContract)
{
ThrowIfCannotSerializeReadOnlyTypes(classContract);
}
WriteClass(classContract);
return (XmlFormatClassWriterDelegate)ilg.EndMethod();
}
internal XmlFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract)
{
ilg = new CodeGenerator();
bool memberAccessFlag = collectionContract.RequiresMemberAccessForWrite(null);
ilg.BeginMethod("Write" + collectionContract.StableName.Name + "ToXml", Globals.TypeOfXmlFormatCollectionWriterDelegate, memberAccessFlag);
InitArgs(collectionContract.UnderlyingType);
if (collectionContract.IsReadOnlyContract)
{
ThrowIfCannotSerializeReadOnlyTypes(collectionContract);
}
WriteCollection(collectionContract);
return (XmlFormatCollectionWriterDelegate)ilg.EndMethod();
}
void InitArgs(Type objType)
{
xmlWriterArg = ilg.GetArg(0);
contextArg = ilg.GetArg(2);
dataContractArg = ilg.GetArg(3);
objectLocal = ilg.DeclareLocal(objType, "objSerialized");
ArgBuilder objectArg = ilg.GetArg(1);
ilg.Load(objectArg);
// Copy the data from the DataTimeOffset object passed in to the DateTimeOffsetAdapter.
// DateTimeOffsetAdapter is used here for serialization purposes to bypass the ISerializable implementation
// on DateTimeOffset; which does not work in partial trust.
if (objType == Globals.TypeOfDateTimeOffsetAdapter)
{
ilg.ConvertValue(objectArg.ArgType, Globals.TypeOfDateTimeOffset);
ilg.Call(XmlFormatGeneratorStatics.GetDateTimeOffsetAdapterMethod);
}
else
{
ilg.ConvertValue(objectArg.ArgType, objType);
}
ilg.Stloc(objectLocal);
}
void ThrowIfCannotSerializeReadOnlyTypes(ClassDataContract classContract)
{
ThrowIfCannotSerializeReadOnlyTypes(XmlFormatGeneratorStatics.ClassSerializationExceptionMessageProperty);
}
void ThrowIfCannotSerializeReadOnlyTypes(CollectionDataContract classContract)
{
ThrowIfCannotSerializeReadOnlyTypes(XmlFormatGeneratorStatics.CollectionSerializationExceptionMessageProperty);
}
void ThrowIfCannotSerializeReadOnlyTypes(PropertyInfo serializationExceptionMessageProperty)
{
ilg.Load(contextArg);
ilg.LoadMember(XmlFormatGeneratorStatics.SerializeReadOnlyTypesProperty);
ilg.IfNot();
ilg.Load(dataContractArg);
ilg.LoadMember(serializationExceptionMessageProperty);
ilg.Load(null);
ilg.Call(XmlFormatGeneratorStatics.ThrowInvalidDataContractExceptionMethod);
ilg.EndIf();
}
void InvokeOnSerializing(ClassDataContract classContract)
{
if (classContract.BaseContract != null)
InvokeOnSerializing(classContract.BaseContract);
if (classContract.OnSerializing != null)
{
ilg.LoadAddress(objectLocal);
ilg.Load(contextArg);
ilg.Call(XmlFormatGeneratorStatics.GetStreamingContextMethod);
ilg.Call(classContract.OnSerializing);
}
}
void InvokeOnSerialized(ClassDataContract classContract)
{
if (classContract.BaseContract != null)
InvokeOnSerialized(classContract.BaseContract);
if (classContract.OnSerialized != null)
{
ilg.LoadAddress(objectLocal);
ilg.Load(contextArg);
ilg.Call(XmlFormatGeneratorStatics.GetStreamingContextMethod);
ilg.Call(classContract.OnSerialized);
}
}
void WriteClass(ClassDataContract classContract)
{
InvokeOnSerializing(classContract);
if (classContract.IsISerializable)
ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteISerializableMethod, xmlWriterArg, objectLocal);
else
{
if (classContract.ContractNamespaces.Length > 1)
{
contractNamespacesLocal = ilg.DeclareLocal(typeof(XmlDictionaryString[]), "contractNamespaces");
ilg.Load(dataContractArg);
ilg.LoadMember(XmlFormatGeneratorStatics.ContractNamespacesField);
ilg.Store(contractNamespacesLocal);
}
memberNamesLocal = ilg.DeclareLocal(typeof(XmlDictionaryString[]), "memberNames");
ilg.Load(dataContractArg);
ilg.LoadMember(XmlFormatGeneratorStatics.MemberNamesField);
ilg.Store(memberNamesLocal);
for (int i = 0; i < classContract.ChildElementNamespaces.Length; i++)
{
if (classContract.ChildElementNamespaces[i] != null)
{
childElementNamespacesLocal = ilg.DeclareLocal(typeof(XmlDictionaryString[]), "childElementNamespaces");
ilg.Load(dataContractArg);
ilg.LoadMember(XmlFormatGeneratorStatics.ChildElementNamespacesProperty);
ilg.Store(childElementNamespacesLocal);
}
}
if (classContract.HasExtensionData)
{
LocalBuilder extensionDataLocal = ilg.DeclareLocal(Globals.TypeOfExtensionDataObject, "extensionData");
ilg.Load(objectLocal);
ilg.ConvertValue(objectLocal.LocalType, Globals.TypeOfIExtensibleDataObject);
ilg.LoadMember(XmlFormatGeneratorStatics.ExtensionDataProperty);
ilg.Store(extensionDataLocal);
ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteExtensionDataMethod, xmlWriterArg, extensionDataLocal, -1);
WriteMembers(classContract, extensionDataLocal, classContract);
}
else
WriteMembers(classContract, null, classContract);
}
InvokeOnSerialized(classContract);
}
int WriteMembers(ClassDataContract classContract, LocalBuilder extensionDataLocal, ClassDataContract derivedMostClassContract)
{
int memberCount = (classContract.BaseContract == null) ? 0 :
WriteMembers(classContract.BaseContract, extensionDataLocal, derivedMostClassContract);
LocalBuilder namespaceLocal = ilg.DeclareLocal(typeof(XmlDictionaryString), "ns");
if (contractNamespacesLocal == null)
{
ilg.Load(dataContractArg);
ilg.LoadMember(XmlFormatGeneratorStatics.NamespaceProperty);
}
else
ilg.LoadArrayElement(contractNamespacesLocal, typeIndex - 1);
ilg.Store(namespaceLocal);
ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, classContract.Members.Count);
for (int i = 0; i < classContract.Members.Count; i++, memberCount++)
{
DataMember member = classContract.Members[i];
Type memberType = member.MemberType;
LocalBuilder memberValue = null;
if (member.IsGetOnlyCollection)
{
ilg.Load(contextArg);
ilg.Call(XmlFormatGeneratorStatics.StoreIsGetOnlyCollectionMethod);
}
if (!member.EmitDefaultValue)
{
memberValue = LoadMemberValue(member);
ilg.IfNotDefaultValue(memberValue);
}
bool writeXsiType = CheckIfMemberHasConflict(member, classContract, derivedMostClassContract);
if (writeXsiType || !TryWritePrimitive(memberType, memberValue, member.MemberInfo, null /*arrayItemIndex*/, namespaceLocal, null /*nameLocal*/, i + childElementIndex))
{
WriteStartElement(memberType, classContract.Namespace, namespaceLocal, null /*nameLocal*/, i + childElementIndex);
if (classContract.ChildElementNamespaces[i + childElementIndex] != null)
{
ilg.Load(xmlWriterArg);
ilg.LoadArrayElement(childElementNamespacesLocal, i + childElementIndex);
ilg.Call(XmlFormatGeneratorStatics.WriteNamespaceDeclMethod);
}
if (memberValue == null)
memberValue = LoadMemberValue(member);
WriteValue(memberValue, writeXsiType);
WriteEndElement();
}
if (classContract.HasExtensionData)
ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteExtensionDataMethod, xmlWriterArg, extensionDataLocal, memberCount);
if (!member.EmitDefaultValue)
{
if (member.IsRequired)
{
ilg.Else();
ilg.Call(null, XmlFormatGeneratorStatics.ThrowRequiredMemberMustBeEmittedMethod, member.Name, classContract.UnderlyingType);
}
ilg.EndIf();
}
}
typeIndex++;
childElementIndex += classContract.Members.Count;
return memberCount;
}
private LocalBuilder LoadMemberValue(DataMember member)
{
ilg.LoadAddress(objectLocal);
ilg.LoadMember(member.MemberInfo);
LocalBuilder memberValue = ilg.DeclareLocal(member.MemberType, member.Name + "Value");
ilg.Stloc(memberValue);
return memberValue;
}
void WriteCollection(CollectionDataContract collectionContract)
{
LocalBuilder itemNamespace = ilg.DeclareLocal(typeof(XmlDictionaryString), "itemNamespace");
ilg.Load(dataContractArg);
ilg.LoadMember(XmlFormatGeneratorStatics.NamespaceProperty);
ilg.Store(itemNamespace);
LocalBuilder itemName = ilg.DeclareLocal(typeof(XmlDictionaryString), "itemName");
ilg.Load(dataContractArg);
ilg.LoadMember(XmlFormatGeneratorStatics.CollectionItemNameProperty);
ilg.Store(itemName);
if (collectionContract.ChildElementNamespace != null)
{
ilg.Load(xmlWriterArg);
ilg.Load(dataContractArg);
ilg.LoadMember(XmlFormatGeneratorStatics.ChildElementNamespaceProperty);
ilg.Call(XmlFormatGeneratorStatics.WriteNamespaceDeclMethod);
}
if (collectionContract.Kind == CollectionKind.Array)
{
Type itemType = collectionContract.ItemType;
LocalBuilder i = ilg.DeclareLocal(Globals.TypeOfInt, "i");
ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementArrayCountMethod, xmlWriterArg, objectLocal);
if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, objectLocal, itemName, itemNamespace))
{
ilg.For(i, 0, objectLocal);
if (!TryWritePrimitive(itemType, null /*value*/, null /*memberInfo*/, i /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/))
{
WriteStartElement(itemType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/);
ilg.LoadArrayElement(objectLocal, i);
LocalBuilder memberValue = ilg.DeclareLocal(itemType, "memberValue");
ilg.Stloc(memberValue);
WriteValue(memberValue, false /*writeXsiType*/);
WriteEndElement();
}
ilg.EndFor();
}
}
else
{
MethodInfo incrementCollectionCountMethod = null;
switch (collectionContract.Kind)
{
case CollectionKind.Collection:
case CollectionKind.List:
case CollectionKind.Dictionary:
incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod;
break;
case CollectionKind.GenericCollection:
case CollectionKind.GenericList:
incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType);
break;
case CollectionKind.GenericDictionary:
incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments()));
break;
}
if (incrementCollectionCountMethod != null)
{
ilg.Call(contextArg, incrementCollectionCountMethod, xmlWriterArg, objectLocal);
}
bool isDictionary = false, isGenericDictionary = false;
Type enumeratorType = null;
Type[] keyValueTypes = null;
if (collectionContract.Kind == CollectionKind.GenericDictionary)
{
isGenericDictionary = true;
keyValueTypes = collectionContract.ItemType.GetGenericArguments();
enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes);
}
else if (collectionContract.Kind == CollectionKind.Dictionary)
{
isDictionary = true;
keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject };
enumeratorType = Globals.TypeOfDictionaryEnumerator;
}
else
{
enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType;
}
MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
if (moveNextMethod == null || getCurrentMethod == null)
{
if (enumeratorType.IsInterface)
{
if (moveNextMethod == null)
moveNextMethod = XmlFormatGeneratorStatics.MoveNextMethod;
if (getCurrentMethod == null)
getCurrentMethod = XmlFormatGeneratorStatics.GetCurrentMethod;
}
else
{
Type ienumeratorInterface = Globals.TypeOfIEnumerator;
CollectionKind kind = collectionContract.Kind;
if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable)
{
Type[] interfaceTypes = enumeratorType.GetInterfaces();
foreach (Type interfaceType in interfaceTypes)
{
if (interfaceType.IsGenericType
&& interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric
&& interfaceType.GetGenericArguments()[0] == collectionContract.ItemType)
{
ienumeratorInterface = interfaceType;
break;
}
}
}
if (moveNextMethod == null)
moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface);
if (getCurrentMethod == null)
getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface);
}
}
Type elementType = getCurrentMethod.ReturnType;
LocalBuilder currentValue = ilg.DeclareLocal(elementType, "currentValue");
LocalBuilder enumerator = ilg.DeclareLocal(enumeratorType, "enumerator");
ilg.Call(objectLocal, collectionContract.GetEnumeratorMethod);
if (isDictionary)
{
ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, Globals.TypeOfIDictionaryEnumerator);
ilg.New(XmlFormatGeneratorStatics.DictionaryEnumeratorCtor);
}
else if (isGenericDictionary)
{
Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes));
ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null);
ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, ctorParam);
ilg.New(dictEnumCtor);
}
ilg.Stloc(enumerator);
ilg.ForEach(currentValue, elementType, enumeratorType, enumerator, getCurrentMethod);
if (incrementCollectionCountMethod == null)
{
ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1);
}
if (!TryWritePrimitive(elementType, currentValue, null /*memberInfo*/, null /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/))
{
WriteStartElement(elementType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/);
if (isGenericDictionary || isDictionary)
{
ilg.Call(dataContractArg, XmlFormatGeneratorStatics.GetItemContractMethod);
ilg.Load(xmlWriterArg);
ilg.Load(currentValue);
ilg.ConvertValue(currentValue.LocalType, Globals.TypeOfObject);
ilg.Load(contextArg);
ilg.Call(XmlFormatGeneratorStatics.WriteXmlValueMethod);
}
else
{
WriteValue(currentValue, false /*writeXsiType*/);
}
WriteEndElement();
}
ilg.EndForEach(moveNextMethod);
}
}
bool TryWritePrimitive(Type type, LocalBuilder value, MemberInfo memberInfo, LocalBuilder arrayItemIndex, LocalBuilder ns, LocalBuilder name, int nameIndex)
{
PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type);
if (primitiveContract == null || primitiveContract.UnderlyingType == Globals.TypeOfObject)
return false;
// load xmlwriter
if (type.IsValueType)
{
ilg.Load(xmlWriterArg);
}
else
{
ilg.Load(contextArg);
ilg.Load(xmlWriterArg);
}
// load primitive value
if (value != null)
{
ilg.Load(value);
}
else if (memberInfo != null)
{
ilg.LoadAddress(objectLocal);
ilg.LoadMember(memberInfo);
}
else
{
ilg.LoadArrayElement(objectLocal, arrayItemIndex);
}
// load name
if (name != null)
{
ilg.Load(name);
}
else
{
ilg.LoadArrayElement(memberNamesLocal, nameIndex);
}
// load namespace
ilg.Load(ns);
// call method to write primitive
ilg.Call(primitiveContract.XmlFormatWriterMethod);
return true;
}
bool TryWritePrimitiveArray(Type type, Type itemType, LocalBuilder value, LocalBuilder itemName, LocalBuilder itemNamespace)
{
PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(itemType);
if (primitiveContract == null)
return false;
string writeArrayMethod = null;
switch (Type.GetTypeCode(itemType))
{
case TypeCode.Boolean:
writeArrayMethod = "WriteBooleanArray";
break;
case TypeCode.DateTime:
writeArrayMethod = "WriteDateTimeArray";
break;
case TypeCode.Decimal:
writeArrayMethod = "WriteDecimalArray";
break;
case TypeCode.Int32:
writeArrayMethod = "WriteInt32Array";
break;
case TypeCode.Int64:
writeArrayMethod = "WriteInt64Array";
break;
case TypeCode.Single:
writeArrayMethod = "WriteSingleArray";
break;
case TypeCode.Double:
writeArrayMethod = "WriteDoubleArray";
break;
default:
break;
}
if (writeArrayMethod != null)
{
ilg.Load(xmlWriterArg);
ilg.Load(value);
ilg.Load(itemName);
ilg.Load(itemNamespace);
ilg.Call(typeof(XmlWriterDelegator).GetMethod(writeArrayMethod, Globals.ScanAllMembers, null, new Type[] { type, typeof(XmlDictionaryString), typeof(XmlDictionaryString) }, null));
return true;
}
return false;
}
void WriteValue(LocalBuilder memberValue, bool writeXsiType)
{
Type memberType = memberValue.LocalType;
if (memberType.IsPointer)
{
ilg.Load(memberValue);
ilg.Load(memberType);
ilg.Call(XmlFormatGeneratorStatics.BoxPointer);
memberType = Globals.TypeOfReflectionPointer;
memberValue = ilg.DeclareLocal(memberType, "memberValueRefPointer");
ilg.Store(memberValue);
}
bool isNullableOfT = (memberType.IsGenericType &&
memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable);
if (memberType.IsValueType && !isNullableOfT)
{
PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
if (primitiveContract != null && !writeXsiType)
ilg.Call(xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue);
else
InternalSerialize(XmlFormatGeneratorStatics.InternalSerializeMethod, memberValue, memberType, writeXsiType);
}
else
{
if (isNullableOfT)
{
memberValue = UnwrapNullableObject(memberValue); //Leaves !HasValue on stack
memberType = memberValue.LocalType;
}
else
{
ilg.Load(memberValue);
ilg.Load(null);
ilg.Ceq();
}
ilg.If();
ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteNullMethod, xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType));
ilg.Else();
PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType);
if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject && !writeXsiType)
{
if (isNullableOfT)
{
ilg.Call(xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue);
}
else
{
ilg.Call(contextArg, primitiveContract.XmlFormatContentWriterMethod, xmlWriterArg, memberValue);
}
}
else
{
if (memberType == Globals.TypeOfObject || //boxed Nullable<T>
memberType == Globals.TypeOfValueType ||
((IList)Globals.TypeOfNullable.GetInterfaces()).Contains(memberType))
{
ilg.Load(memberValue);
ilg.ConvertValue(memberValue.LocalType, Globals.TypeOfObject);
memberValue = ilg.DeclareLocal(Globals.TypeOfObject, "unwrappedMemberValue");
memberType = memberValue.LocalType;
ilg.Stloc(memberValue);
ilg.If(memberValue, Cmp.EqualTo, null);
ilg.Call(contextArg, XmlFormatGeneratorStatics.WriteNullMethod, xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType));
ilg.Else();
}
InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod),
memberValue, memberType, writeXsiType);
if (memberType == Globals.TypeOfObject) //boxed Nullable<T>
ilg.EndIf();
}
ilg.EndIf();
}
}
void InternalSerialize(MethodInfo methodInfo, LocalBuilder memberValue, Type memberType, bool writeXsiType)
{
ilg.Load(contextArg);
ilg.Load(xmlWriterArg);
ilg.Load(memberValue);
ilg.ConvertValue(memberValue.LocalType, Globals.TypeOfObject);
LocalBuilder typeHandleValue = ilg.DeclareLocal(typeof(RuntimeTypeHandle), "typeHandleValue");
ilg.Call(null, typeof(Type).GetMethod("GetTypeHandle"), memberValue);
ilg.Stloc(typeHandleValue);
ilg.LoadAddress(typeHandleValue);
ilg.Ldtoken(memberType);
ilg.Call(typeof(RuntimeTypeHandle).GetMethod("Equals", new Type[] { typeof(RuntimeTypeHandle) }));
ilg.Load(writeXsiType);
ilg.Load(DataContract.GetId(memberType.TypeHandle));
ilg.Ldtoken(memberType);
ilg.Call(methodInfo);
}
LocalBuilder UnwrapNullableObject(LocalBuilder memberValue)// Leaves !HasValue on stack
{
Type memberType = memberValue.LocalType;
Label onNull = ilg.DefineLabel();
Label end = ilg.DefineLabel();
ilg.Load(memberValue);
while (memberType.IsGenericType && memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable)
{
Type innerType = memberType.GetGenericArguments()[0];
ilg.Dup();
ilg.Call(XmlFormatGeneratorStatics.GetHasValueMethod.MakeGenericMethod(innerType));
ilg.Brfalse(onNull);
ilg.Call(XmlFormatGeneratorStatics.GetNullableValueMethod.MakeGenericMethod(innerType));
memberType = innerType;
}
memberValue = ilg.DeclareLocal(memberType, "nullableUnwrappedMemberValue");
ilg.Stloc(memberValue);
ilg.Load(false); //isNull
ilg.Br(end);
ilg.MarkLabel(onNull);
ilg.Pop();
ilg.Call(XmlFormatGeneratorStatics.GetDefaultValueMethod.MakeGenericMethod(memberType));
ilg.Stloc(memberValue);
ilg.Load(true); //isNull
ilg.MarkLabel(end);
return memberValue;
}
bool NeedsPrefix(Type type, XmlDictionaryString ns)
{
return type == Globals.TypeOfXmlQualifiedName && (ns != null && ns.Value != null && ns.Value.Length > 0);
}
void WriteStartElement(Type type, XmlDictionaryString ns, LocalBuilder namespaceLocal, LocalBuilder nameLocal, int nameIndex)
{
bool needsPrefix = NeedsPrefix(type, ns);
ilg.Load(xmlWriterArg);
// prefix
if (needsPrefix)
ilg.Load(Globals.ElementPrefix);
// localName
if (nameLocal == null)
ilg.LoadArrayElement(memberNamesLocal, nameIndex);
else
ilg.Load(nameLocal);
// namespace
ilg.Load(namespaceLocal);
ilg.Call(needsPrefix ? XmlFormatGeneratorStatics.WriteStartElementMethod3 : XmlFormatGeneratorStatics.WriteStartElementMethod2);
}
void WriteEndElement()
{
ilg.Call(xmlWriterArg, XmlFormatGeneratorStatics.WriteEndElementMethod);
}
bool CheckIfMemberHasConflict(DataMember member, ClassDataContract classContract, ClassDataContract derivedMostClassContract)
{
// Check for conflict with base type members
if (CheckIfConflictingMembersHaveDifferentTypes(member))
return true;
// Check for conflict with derived type members
string name = member.Name;
string ns = classContract.StableName.Namespace;
ClassDataContract currentContract = derivedMostClassContract;
while (currentContract != null && currentContract != classContract)
{
if (ns == currentContract.StableName.Namespace)
{
List<DataMember> members = currentContract.Members;
for (int j = 0; j < members.Count; j++)
{
if (name == members[j].Name)
return CheckIfConflictingMembersHaveDifferentTypes(members[j]);
}
}
currentContract = currentContract.BaseContract;
}
return false;
}
bool CheckIfConflictingMembersHaveDifferentTypes(DataMember member)
{
while (member.ConflictingMember != null)
{
if (member.MemberType != member.ConflictingMember.MemberType)
return true;
member = member.ConflictingMember;
}
return false;
}
#if NotUsed
static Hashtable nsToPrefixTable = new Hashtable(4);
internal static string GetPrefix(string ns)
{
string prefix = (string)nsToPrefixTable[ns];
if (prefix == null)
{
lock (nsToPrefixTable)
{
if (prefix == null)
{
prefix = "p" + nsToPrefixTable.Count;
nsToPrefixTable.Add(ns, prefix);
}
}
}
return prefix;
}
#endif
}
}
}

View File

@@ -0,0 +1,418 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Xml;
using DataContractResolver = System.Runtime.Serialization.DataContractResolver;
using FormatterConverter = System.Runtime.Serialization.FormatterConverter;
using IFormatterConverter = System.Runtime.Serialization.IFormatterConverter;
using SerializationException = System.Runtime.Serialization.SerializationException;
namespace Compat.Runtime.Serialization
{
using DataContractDictionary = Dictionary<XmlQualifiedName, DataContract>;
public abstract class XmlObjectSerializer
{
public abstract void WriteStartObject(XmlDictionaryWriter writer, object graph);
public abstract void WriteObjectContent(XmlDictionaryWriter writer, object graph);
public abstract void WriteEndObject(XmlDictionaryWriter writer);
public virtual void WriteObject(Stream stream, object graph)
{
stream = stream ?? throw new ArgumentNullException(nameof(stream));
XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream: stream, encoding: Encoding.UTF8, ownsStream: false);
WriteObject(writer, graph);
writer.Flush();
}
public virtual void WriteObject(XmlWriter writer, object graph)
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
WriteObject(XmlDictionaryWriter.CreateDictionaryWriter(writer), graph);
}
public virtual void WriteStartObject(XmlWriter writer, object graph)
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
WriteStartObject(XmlDictionaryWriter.CreateDictionaryWriter(writer), graph);
}
public virtual void WriteObjectContent(XmlWriter writer, object graph)
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
WriteObjectContent(XmlDictionaryWriter.CreateDictionaryWriter(writer), graph);
}
public virtual void WriteEndObject(XmlWriter writer)
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
WriteEndObject(XmlDictionaryWriter.CreateDictionaryWriter(writer));
}
public virtual void WriteObject(XmlDictionaryWriter writer, object graph)
{
WriteObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
}
internal void WriteObjectHandleExceptions(XmlWriterDelegator writer, object graph)
{
WriteObjectHandleExceptions(writer, graph, null);
}
internal void WriteObjectHandleExceptions(XmlWriterDelegator writer, object graph, DataContractResolver dataContractResolver)
{
try
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
InternalWriteObject(writer, graph, dataContractResolver);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateSerializationException(GetTypeInfoError(SR.ErrorSerializing, GetSerializeType(graph), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateSerializationException(GetTypeInfoError(SR.ErrorSerializing, GetSerializeType(graph), ex), ex));
}
}
internal virtual DataContractDictionary KnownDataContracts => null;
internal virtual void InternalWriteObject(XmlWriterDelegator writer, object graph)
{
WriteStartObject(writer.Writer, graph);
WriteObjectContent(writer.Writer, graph);
WriteEndObject(writer.Writer);
}
internal virtual void InternalWriteObject(XmlWriterDelegator writer, object graph, DataContractResolver dataContractResolver)
{
InternalWriteObject(writer, graph);
}
internal virtual void InternalWriteStartObject(XmlWriterDelegator writer, object graph)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
internal virtual void InternalWriteObjectContent(XmlWriterDelegator writer, object graph)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
internal virtual void InternalWriteEndObject(XmlWriterDelegator writer)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
internal void WriteStartObjectHandleExceptions(XmlWriterDelegator writer, object graph)
{
try
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
InternalWriteStartObject(writer, graph);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorWriteStartObject, GetSerializeType(graph), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorWriteStartObject, GetSerializeType(graph), ex), ex));
}
}
internal void WriteObjectContentHandleExceptions(XmlWriterDelegator writer, object graph)
{
try
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
if (writer.WriteState != WriteState.Element)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.XmlWriterMustBeInElement, writer.WriteState)));
}
InternalWriteObjectContent(writer, graph);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorSerializing, GetSerializeType(graph), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorSerializing, GetSerializeType(graph), ex), ex));
}
}
internal void WriteEndObjectHandleExceptions(XmlWriterDelegator writer)
{
try
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
InternalWriteEndObject(writer);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorWriteEndObject, null, ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorWriteEndObject, null, ex), ex));
}
}
internal void WriteRootElement(XmlWriterDelegator writer, DataContract contract, XmlDictionaryString name, XmlDictionaryString ns, bool needsContractNsAtRoot)
{
if (name == null) // root name not set explicitly
{
if (!contract.HasRoot)
{
return;
}
contract.WriteRootElement(writer, contract.TopLevelElementName, contract.TopLevelElementNamespace);
}
else
{
contract.WriteRootElement(writer, name, ns);
if (needsContractNsAtRoot)
{
writer.WriteNamespaceDecl(contract.Namespace);
}
}
}
internal bool CheckIfNeedsContractNsAtRoot(XmlDictionaryString name, XmlDictionaryString ns, DataContract contract)
{
if (name == null)
{
return false;
}
if (contract.IsBuiltInDataContract || !contract.CanContainReferences || contract.IsISerializable)
{
return false;
}
string contractNs = contract.Namespace?.Value;
if (string.IsNullOrEmpty(contractNs) || contractNs == ns?.Value)
{
return false;
}
return true;
}
internal static void WriteNull(XmlWriterDelegator writer)
{
writer.WriteAttributeBool(Globals.XsiPrefix, DictionaryGlobals.XsiNilLocalName, DictionaryGlobals.SchemaInstanceNamespace, true);
}
internal static bool IsContractDeclared(DataContract contract, DataContract declaredContract)
{
return (object.ReferenceEquals(contract.Name, declaredContract.Name) && object.ReferenceEquals(contract.Namespace, declaredContract.Namespace))
|| (contract.Name.Value == declaredContract.Name.Value && contract.Namespace.Value == declaredContract.Namespace.Value);
}
public virtual object ReadObject(Stream stream)
{
stream = stream ?? throw new ArgumentNullException(nameof(stream));
return ReadObject(XmlDictionaryReader.CreateTextReader(stream, XmlDictionaryReaderQuotas.Max));
}
public virtual object ReadObject(XmlReader reader)
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return ReadObject(XmlDictionaryReader.CreateDictionaryReader(reader));
}
public virtual object ReadObject(XmlDictionaryReader reader)
{
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), true /*verifyObjectName*/);
}
public virtual object ReadObject(XmlReader reader, bool verifyObjectName)
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return ReadObject(XmlDictionaryReader.CreateDictionaryReader(reader), verifyObjectName);
}
public abstract object ReadObject(XmlDictionaryReader reader, bool verifyObjectName);
public virtual bool IsStartObject(XmlReader reader)
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return IsStartObject(XmlDictionaryReader.CreateDictionaryReader(reader));
}
public abstract bool IsStartObject(XmlDictionaryReader reader);
internal virtual object InternalReadObject(XmlReaderDelegator reader, bool verifyObjectName)
{
return ReadObject(reader.UnderlyingReader, verifyObjectName);
}
internal virtual object InternalReadObject(XmlReaderDelegator reader, bool verifyObjectName, DataContractResolver dataContractResolver)
{
return InternalReadObject(reader, verifyObjectName);
}
internal virtual bool InternalIsStartObject(XmlReaderDelegator reader)
{
Fx.Assert("XmlObjectSerializer.InternalIsStartObject should never get called");
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
internal object ReadObjectHandleExceptions(XmlReaderDelegator reader, bool verifyObjectName)
{
return ReadObjectHandleExceptions(reader, verifyObjectName, null);
}
internal object ReadObjectHandleExceptions(XmlReaderDelegator reader, bool verifyObjectName, DataContractResolver dataContractResolver)
{
try
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return InternalReadObject(reader, verifyObjectName, dataContractResolver);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorDeserializing, GetDeserializeType(), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorDeserializing, GetDeserializeType(), ex), ex));
}
}
internal bool IsStartObjectHandleExceptions(XmlReaderDelegator reader)
{
try
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return InternalIsStartObject(reader);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorIsStartObject, GetDeserializeType(), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorIsStartObject, GetDeserializeType(), ex), ex));
}
}
internal bool IsRootXmlAny(XmlDictionaryString rootName, DataContract contract)
{
return (rootName == null) && !contract.HasRoot;
}
internal bool IsStartElement(XmlReaderDelegator reader)
{
return (reader.MoveToElement() || reader.IsStartElement());
}
internal bool IsRootElement(XmlReaderDelegator reader, DataContract contract, XmlDictionaryString name, XmlDictionaryString ns)
{
reader.MoveToElement();
if (name != null) // root name set explicitly
{
return reader.IsStartElement(name, ns);
}
else
{
if (!contract.HasRoot)
{
return reader.IsStartElement();
}
if (reader.IsStartElement(contract.TopLevelElementName, contract.TopLevelElementNamespace))
{
return true;
}
ClassDataContract classContract = contract as ClassDataContract;
if (classContract != null)
{
classContract = classContract.BaseContract;
}
while (classContract != null)
{
if (reader.IsStartElement(classContract.TopLevelElementName, classContract.TopLevelElementNamespace))
{
return true;
}
classContract = classContract.BaseContract;
}
if (classContract == null)
{
DataContract objectContract = PrimitiveDataContract.GetPrimitiveDataContract(Globals.TypeOfObject);
if (reader.IsStartElement(objectContract.TopLevelElementName, objectContract.TopLevelElementNamespace))
{
return true;
}
}
return false;
}
}
internal static string TryAddLineInfo(XmlReaderDelegator reader, string errorMessage)
{
if (reader.HasLineInfo())
{
return string.Format(CultureInfo.InvariantCulture, "{0} {1}", SR.Format(SR.ErrorInLine, reader.LineNumber, reader.LinePosition), errorMessage);
}
return errorMessage;
}
internal static Exception CreateSerializationExceptionWithReaderDetails(string errorMessage, XmlReaderDelegator reader)
{
return XmlObjectSerializer.CreateSerializationException(TryAddLineInfo(reader, SR.Format(SR.EncounteredWithNameNamespace, errorMessage, reader.NodeType, reader.LocalName, reader.NamespaceURI)));
}
internal static SerializationException CreateSerializationException(string errorMessage)
{
return XmlObjectSerializer.CreateSerializationException(errorMessage, null);
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static SerializationException CreateSerializationException(string errorMessage, Exception innerException)
{
return new SerializationException(errorMessage, innerException);
}
private static string GetTypeInfoError(string errorMessage, Type type, Exception innerException)
{
string typeInfo = (type == null) ? string.Empty : SR.Format(SR.ErrorTypeInfo, DataContract.GetClrTypeFullName(type));
string innerExceptionMessage = innerException?.Message ?? string.Empty;
return SR.Format(errorMessage, typeInfo, innerExceptionMessage);
}
internal virtual Type GetSerializeType(object graph)
{
return graph?.GetType();
}
internal virtual Type GetDeserializeType()
{
return null;
}
private static IFormatterConverter formatterConverter;
internal static IFormatterConverter FormatterConverter
{
get
{
if (formatterConverter == null)
{
formatterConverter = new FormatterConverter();
}
return formatterConverter;
}
}
}
}

View File

@@ -0,0 +1,342 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Security;
using System.Xml;
namespace Compat.Runtime.Serialization
{
using DataContractDictionary = Dictionary<XmlQualifiedName, DataContract>;
internal class XmlObjectSerializerContext
{
protected XmlObjectSerializer serializer;
protected DataContract rootTypeDataContract;
internal ScopedKnownTypes scopedKnownTypes = new ScopedKnownTypes();
protected DataContractDictionary serializerKnownDataContracts;
private bool isSerializerKnownDataContractsSetExplicit;
protected IList<Type> serializerKnownTypeList;
private int itemCount;
private readonly int maxItemsInObjectGraph;
private System.Runtime.Serialization.StreamingContext streamingContext;
private readonly bool ignoreExtensionDataObject;
private readonly System.Runtime.Serialization.DataContractResolver dataContractResolver;
private KnownTypeDataContractResolver knownTypeResolver;
internal XmlObjectSerializerContext(
XmlObjectSerializer serializer,
int maxItemsInObjectGraph,
System.Runtime.Serialization.StreamingContext streamingContext,
bool ignoreExtensionDataObject,
System.Runtime.Serialization.DataContractResolver dataContractResolver)
{
this.serializer = serializer;
itemCount = 1;
this.maxItemsInObjectGraph = maxItemsInObjectGraph;
this.streamingContext = streamingContext;
this.ignoreExtensionDataObject = ignoreExtensionDataObject;
this.dataContractResolver = dataContractResolver;
}
internal XmlObjectSerializerContext(XmlObjectSerializer serializer,
int maxItemsInObjectGraph,
System.Runtime.Serialization.StreamingContext streamingContext,
bool ignoreExtensionDataObject)
: this(serializer, maxItemsInObjectGraph, streamingContext, ignoreExtensionDataObject, null)
{
}
internal XmlObjectSerializerContext(
DataContractSerializer serializer,
DataContract rootTypeDataContract,
System.Runtime.Serialization.DataContractResolver dataContractResolver)
: this(serializer,
serializer.MaxItemsInObjectGraph,
new System.Runtime.Serialization.StreamingContext(System.Runtime.Serialization.StreamingContextStates.All),
serializer.IgnoreExtensionDataObject,
dataContractResolver)
{
this.rootTypeDataContract = rootTypeDataContract;
serializerKnownTypeList = serializer.knownTypeList;
}
internal XmlObjectSerializerContext(NetDataContractSerializer serializer)
: this(serializer,
serializer.MaxItemsInObjectGraph,
serializer.Context,
serializer.IgnoreExtensionDataObject)
{
}
internal virtual SerializationMode Mode => SerializationMode.SharedContract;
internal virtual bool IsGetOnlyCollection
{
get => false;
set { }
}
public System.Runtime.Serialization.StreamingContext GetStreamingContext()
{
return streamingContext;
}
private static MethodInfo incrementItemCountMethod;
internal static MethodInfo IncrementItemCountMethod
{
get
{
if (incrementItemCountMethod == null)
{
incrementItemCountMethod = typeof(XmlObjectSerializerContext).GetMethod("IncrementItemCount", Globals.ScanAllMembers);
}
return incrementItemCountMethod;
}
}
public void IncrementItemCount(int count)
{
if (count > maxItemsInObjectGraph - itemCount)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExceededMaxItemsQuota, maxItemsInObjectGraph)));
}
itemCount += count;
}
internal int RemainingItemCount => maxItemsInObjectGraph - itemCount;
internal bool IgnoreExtensionDataObject => ignoreExtensionDataObject;
protected System.Runtime.Serialization.DataContractResolver DataContractResolver => dataContractResolver;
protected KnownTypeDataContractResolver KnownTypeResolver
{
get
{
if (knownTypeResolver == null)
{
knownTypeResolver = new KnownTypeDataContractResolver(this);
}
return knownTypeResolver;
}
}
internal DataContract GetDataContract(Type type)
{
return GetDataContract(type.TypeHandle, type);
}
internal virtual DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
{
if (IsGetOnlyCollection)
{
return DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(typeHandle), typeHandle, type, Mode);
}
else
{
return DataContract.GetDataContract(typeHandle, type, Mode);
}
}
internal virtual DataContract GetDataContractSkipValidation(int typeId, RuntimeTypeHandle typeHandle, Type type)
{
if (IsGetOnlyCollection)
{
return DataContract.GetGetOnlyCollectionDataContractSkipValidation(typeId, typeHandle, type);
}
else
{
return DataContract.GetDataContractSkipValidation(typeId, typeHandle, type);
}
}
internal virtual DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
{
if (IsGetOnlyCollection)
{
return DataContract.GetGetOnlyCollectionDataContract(id, typeHandle, null /*type*/, Mode);
}
else
{
return DataContract.GetDataContract(id, typeHandle, Mode);
}
}
internal virtual void CheckIfTypeSerializable(Type memberType, bool isMemberTypeSerializable)
{
if (!isMemberTypeSerializable)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.TypeNotSerializable, memberType)));
}
}
internal virtual Type GetSurrogatedType(Type type)
{
return type;
}
private DataContractDictionary SerializerKnownDataContracts
{
get
{
// This field must be initialized during construction by serializers using data contracts.
if (!isSerializerKnownDataContractsSetExplicit)
{
serializerKnownDataContracts = serializer.KnownDataContracts;
isSerializerKnownDataContractsSetExplicit = true;
}
return serializerKnownDataContracts;
}
}
private DataContract GetDataContractFromSerializerKnownTypes(XmlQualifiedName qname)
{
DataContractDictionary serializerKnownDataContracts = SerializerKnownDataContracts;
if (serializerKnownDataContracts == null)
{
return null;
}
return serializerKnownDataContracts.TryGetValue(qname, out DataContract outDataContract) ? outDataContract : null;
}
internal static DataContractDictionary GetDataContractsForKnownTypes(IList<Type> knownTypeList)
{
if (knownTypeList == null)
{
return null;
}
DataContractDictionary dataContracts = new DataContractDictionary();
Dictionary<Type, Type> typesChecked = new Dictionary<Type, Type>();
for (int i = 0; i < knownTypeList.Count; i++)
{
Type knownType = knownTypeList[i];
if (knownType == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.NullKnownType, "knownTypes")));
}
DataContract.CheckAndAdd(knownType, typesChecked, ref dataContracts);
}
return dataContracts;
}
internal bool IsKnownType(DataContract dataContract, DataContractDictionary knownDataContracts, Type declaredType)
{
bool knownTypesAddedInCurrentScope = false;
if (knownDataContracts != null)
{
scopedKnownTypes.Push(knownDataContracts);
knownTypesAddedInCurrentScope = true;
}
bool isKnownType = IsKnownType(dataContract, declaredType);
if (knownTypesAddedInCurrentScope)
{
scopedKnownTypes.Pop();
}
return isKnownType;
}
internal bool IsKnownType(DataContract dataContract, Type declaredType)
{
DataContract knownContract = ResolveDataContractFromKnownTypes(dataContract.StableName.Name, dataContract.StableName.Namespace, null /*memberTypeContract*/, declaredType);
return knownContract != null && knownContract.UnderlyingType == dataContract.UnderlyingType;
}
private DataContract ResolveDataContractFromKnownTypes(XmlQualifiedName typeName)
{
DataContract dataContract = PrimitiveDataContract.GetPrimitiveDataContract(typeName.Name, typeName.Namespace);
if (dataContract == null)
{
dataContract = scopedKnownTypes.GetDataContract(typeName);
if (dataContract == null)
{
dataContract = GetDataContractFromSerializerKnownTypes(typeName);
}
}
return dataContract;
}
private DataContract ResolveDataContractFromDataContractResolver(XmlQualifiedName typeName, Type declaredType)
{
Type dataContractType = DataContractResolver.ResolveName(typeName.Name, typeName.Namespace, declaredType, KnownTypeResolver);
if (dataContractType == null)
{
return null;
}
else
{
return GetDataContract(dataContractType);
}
}
internal Type ResolveNameFromKnownTypes(XmlQualifiedName typeName)
{
DataContract dataContract = ResolveDataContractFromKnownTypes(typeName);
if (dataContract == null)
{
return null;
}
else
{
return dataContract.OriginalUnderlyingType;
}
}
protected DataContract ResolveDataContractFromKnownTypes(string typeName, string typeNs, DataContract memberTypeContract, Type declaredType)
{
XmlQualifiedName qname = new XmlQualifiedName(typeName, typeNs);
DataContract dataContract;
if (DataContractResolver == null)
{
dataContract = ResolveDataContractFromKnownTypes(qname);
}
else
{
dataContract = ResolveDataContractFromDataContractResolver(qname, declaredType);
}
if (dataContract == null)
{
if (memberTypeContract != null
&& !memberTypeContract.UnderlyingType.IsInterface
&& memberTypeContract.StableName == qname)
{
dataContract = memberTypeContract;
}
if (dataContract == null && rootTypeDataContract != null)
{
dataContract = ResolveDataContractFromRootDataContract(qname);
}
}
return dataContract;
}
protected virtual DataContract ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName)
{
if (rootTypeDataContract.StableName == typeQName)
{
return rootTypeDataContract;
}
CollectionDataContract collectionContract = rootTypeDataContract as CollectionDataContract;
while (collectionContract != null)
{
DataContract itemContract = GetDataContract(GetSurrogatedType(collectionContract.ItemType));
if (itemContract.StableName == typeQName)
{
return itemContract;
}
collectionContract = itemContract as CollectionDataContract;
}
return null;
}
}
}

View File

@@ -0,0 +1,533 @@
using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters;
namespace Compat.Runtime.Serialization
{
internal class XmlObjectSerializerReadContextComplex : XmlObjectSerializerReadContext
{
private static readonly Hashtable dataContractTypeCache = new Hashtable();
private readonly bool preserveObjectReferences;
protected IDataContractSurrogate dataContractSurrogate;
private readonly SerializationMode mode;
private readonly System.Runtime.Serialization.SerializationBinder binder;
private readonly System.Runtime.Serialization.ISurrogateSelector surrogateSelector;
private readonly FormatterAssemblyStyle assemblyFormat;
private Hashtable surrogateDataContracts;
internal XmlObjectSerializerReadContextComplex(
DataContractSerializer serializer,
DataContract rootTypeDataContract,
System.Runtime.Serialization.DataContractResolver dataContractResolver)
: base(serializer, rootTypeDataContract, dataContractResolver)
{
mode = SerializationMode.SharedContract;
preserveObjectReferences = serializer.PreserveObjectReferences;
dataContractSurrogate = serializer.DataContractSurrogate;
}
internal XmlObjectSerializerReadContextComplex(NetDataContractSerializer serializer)
: base(serializer)
{
mode = SerializationMode.SharedType;
preserveObjectReferences = true;
binder = serializer.Binder;
surrogateSelector = serializer.SurrogateSelector;
assemblyFormat = serializer.AssemblyFormat;
}
internal XmlObjectSerializerReadContextComplex(XmlObjectSerializer serializer, int maxItemsInObjectGraph, System.Runtime.Serialization.StreamingContext streamingContext, bool ignoreExtensionDataObject)
: base(serializer, maxItemsInObjectGraph, streamingContext, ignoreExtensionDataObject)
{
}
internal override SerializationMode Mode => mode;
internal override DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
{
DataContract dataContract = null;
if (mode == SerializationMode.SharedType && surrogateSelector != null)
{
dataContract = NetDataContractSerializer.GetDataContractFromSurrogateSelector(surrogateSelector, GetStreamingContext(), typeHandle, null /*type*/, ref surrogateDataContracts);
}
if (dataContract != null)
{
if (IsGetOnlyCollection && dataContract is SurrogateDataContract)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
}
return dataContract;
}
return base.GetDataContract(id, typeHandle);
}
internal override DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
{
DataContract dataContract = null;
if (mode == SerializationMode.SharedType && surrogateSelector != null)
{
dataContract = NetDataContractSerializer.GetDataContractFromSurrogateSelector(surrogateSelector, GetStreamingContext(), typeHandle, type, ref surrogateDataContracts);
}
if (dataContract != null)
{
if (IsGetOnlyCollection && dataContract is SurrogateDataContract)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
}
return dataContract;
}
return base.GetDataContract(typeHandle, type);
}
public override object InternalDeserialize(XmlReaderDelegator xmlReader, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle, string name, string ns)
{
if (mode == SerializationMode.SharedContract)
{
if (dataContractSurrogate == null)
{
return base.InternalDeserialize(xmlReader, declaredTypeID, declaredTypeHandle, name, ns);
}
else
{
return InternalDeserializeWithSurrogate(xmlReader, Type.GetTypeFromHandle(declaredTypeHandle), null /*surrogateDataContract*/, name, ns);
}
}
else
{
return InternalDeserializeInSharedTypeMode(xmlReader, declaredTypeID, Type.GetTypeFromHandle(declaredTypeHandle), name, ns);
}
}
internal override object InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, string name, string ns)
{
if (mode == SerializationMode.SharedContract)
{
if (dataContractSurrogate == null)
{
return base.InternalDeserialize(xmlReader, declaredType, name, ns);
}
else
{
return InternalDeserializeWithSurrogate(xmlReader, declaredType, null /*surrogateDataContract*/, name, ns);
}
}
else
{
return InternalDeserializeInSharedTypeMode(xmlReader, -1, declaredType, name, ns);
}
}
internal override object InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, string name, string ns)
{
if (mode == SerializationMode.SharedContract)
{
if (dataContractSurrogate == null)
{
return base.InternalDeserialize(xmlReader, declaredType, dataContract, name, ns);
}
else
{
return InternalDeserializeWithSurrogate(xmlReader, declaredType, dataContract, name, ns);
}
}
else
{
return InternalDeserializeInSharedTypeMode(xmlReader, -1, declaredType, name, ns);
}
}
private object InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, int declaredTypeID, Type declaredType, string name, string ns)
{
object retObj = null;
if (TryHandleNullOrRef(xmlReader, declaredType, name, ns, ref retObj))
{
return retObj;
}
DataContract dataContract;
string assemblyName = attributes.ClrAssembly;
string typeName = attributes.ClrType;
if (assemblyName != null && typeName != null)
{
dataContract = ResolveDataContractInSharedTypeMode(assemblyName, typeName, out Assembly assembly, out Type type);
if (dataContract == null)
{
if (assembly == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.AssemblyNotFound, assemblyName)));
}
if (type == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ClrTypeNotFound, assembly.FullName, typeName)));
}
}
//Array covariance is not supported in XSD. If declared type is array, data is sent in format of base array
if (declaredType != null && declaredType.IsArray)
{
dataContract = (declaredTypeID < 0) ? GetDataContract(declaredType) : GetDataContract(declaredTypeID, declaredType.TypeHandle);
}
}
else
{
if (assemblyName != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(XmlObjectSerializer.TryAddLineInfo(xmlReader, SR.Format(SR.AttributeNotFound, Globals.SerializationNamespace, Globals.ClrTypeLocalName, xmlReader.NodeType, xmlReader.NamespaceURI, xmlReader.LocalName))));
}
else if (typeName != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(XmlObjectSerializer.TryAddLineInfo(xmlReader, SR.Format(SR.AttributeNotFound, Globals.SerializationNamespace, Globals.ClrAssemblyLocalName, xmlReader.NodeType, xmlReader.NamespaceURI, xmlReader.LocalName))));
}
else if (declaredType == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(XmlObjectSerializer.TryAddLineInfo(xmlReader, SR.Format(SR.AttributeNotFound, Globals.SerializationNamespace, Globals.ClrTypeLocalName, xmlReader.NodeType, xmlReader.NamespaceURI, xmlReader.LocalName))));
}
dataContract = (declaredTypeID < 0) ? GetDataContract(declaredType) : GetDataContract(declaredTypeID, declaredType.TypeHandle);
}
return ReadDataContractValue(dataContract, xmlReader);
}
private object InternalDeserializeWithSurrogate(XmlReaderDelegator xmlReader, Type declaredType, DataContract surrogateDataContract, string name, string ns)
{
DataContract dataContract = surrogateDataContract ??
GetDataContract(DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, declaredType));
if (IsGetOnlyCollection && dataContract.UnderlyingType != declaredType)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
DataContract.GetClrTypeFullName(declaredType))));
}
ReadAttributes(xmlReader);
string objectId = GetObjectId();
object oldObj = InternalDeserialize(xmlReader, name, ns, declaredType, ref dataContract);
object obj = DataContractSurrogateCaller.GetDeserializedObject(dataContractSurrogate, oldObj, dataContract.UnderlyingType, declaredType);
ReplaceDeserializedObject(objectId, oldObj, obj);
return obj;
}
private Type ResolveDataContractTypeInSharedTypeMode(string assemblyName, string typeName, out Assembly assembly)
{
assembly = null;
Type type = null;
if (binder != null)
{
type = binder.BindToType(assemblyName, typeName);
}
if (type == null)
{
XmlObjectDataContractTypeKey key = new XmlObjectDataContractTypeKey(assemblyName, typeName);
XmlObjectDataContractTypeInfo dataContractTypeInfo = (XmlObjectDataContractTypeInfo)dataContractTypeCache[key];
if (dataContractTypeInfo == null)
{
if (assemblyFormat == FormatterAssemblyStyle.Full)
{
if (assemblyName == Globals.MscorlibAssemblyName)
{
assembly = Globals.TypeOfInt.Assembly;
}
else
{
assembly = Assembly.Load(assemblyName);
}
if (assembly != null)
{
type = assembly.GetType(typeName);
}
}
else
{
assembly = XmlObjectSerializerReadContextComplex.ResolveSimpleAssemblyName(assemblyName);
if (assembly != null)
{
// Catching any exceptions that could be thrown from a failure on assembly load
// This is necessary, for example, if there are generic parameters that are qualified with a version of the assembly that predates the one available
try
{
type = assembly.GetType(typeName);
}
catch (TypeLoadException) { }
catch (FileNotFoundException) { }
catch (FileLoadException) { }
catch (BadImageFormatException) { }
if (type == null)
{
type = Type.GetType(typeName, XmlObjectSerializerReadContextComplex.ResolveSimpleAssemblyName, new TopLevelAssemblyTypeResolver(assembly).ResolveType, false /* throwOnError */);
}
}
}
if (type != null)
{
CheckTypeForwardedTo(assembly, type.Assembly, type);
dataContractTypeInfo = new XmlObjectDataContractTypeInfo(assembly, type);
lock (dataContractTypeCache)
{
if (!dataContractTypeCache.ContainsKey(key))
{
dataContractTypeCache[key] = dataContractTypeInfo;
}
}
}
}
else
{
assembly = dataContractTypeInfo.Assembly;
type = dataContractTypeInfo.Type;
}
}
return type;
}
private DataContract ResolveDataContractInSharedTypeMode(string assemblyName, string typeName, out Assembly assembly, out Type type)
{
type = ResolveDataContractTypeInSharedTypeMode(assemblyName, typeName, out assembly);
if (type != null)
{
return GetDataContract(type);
}
return null;
}
protected override DataContract ResolveDataContractFromTypeName()
{
if (mode == SerializationMode.SharedContract)
{
return base.ResolveDataContractFromTypeName();
}
else
{
if (attributes.ClrAssembly != null && attributes.ClrType != null)
{
return ResolveDataContractInSharedTypeMode(attributes.ClrAssembly, attributes.ClrType, out Assembly assembly, out Type type);
}
}
return null;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private bool CheckIfTypeSerializableForSharedTypeMode(Type memberType)
{
Fx.Assert(surrogateSelector != null, "Method should not be called when surrogateSelector is null.");
return (surrogateSelector.GetSurrogate(memberType, GetStreamingContext(), out System.Runtime.Serialization.ISurrogateSelector surrogateSelectorNotUsed) != null);
}
internal override void CheckIfTypeSerializable(Type memberType, bool isMemberTypeSerializable)
{
if (mode == SerializationMode.SharedType && surrogateSelector != null &&
CheckIfTypeSerializableForSharedTypeMode(memberType))
{
return;
}
else
{
if (dataContractSurrogate != null)
{
while (memberType.IsArray)
{
memberType = memberType.GetElementType();
}
memberType = DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, memberType);
if (!DataContract.IsTypeSerializable(memberType))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.TypeNotSerializable, memberType)));
}
return;
}
}
base.CheckIfTypeSerializable(memberType, isMemberTypeSerializable);
}
internal override Type GetSurrogatedType(Type type)
{
if (dataContractSurrogate == null)
{
return base.GetSurrogatedType(type);
}
else
{
type = DataContract.UnwrapNullableType(type);
Type surrogateType = DataContractSerializer.GetSurrogatedType(dataContractSurrogate, type);
if (IsGetOnlyCollection && surrogateType != type)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
DataContract.GetClrTypeFullName(type))));
}
else
{
return surrogateType;
}
}
}
#if USE_REFEMIT
public override int GetArraySize()
#else
internal override int GetArraySize()
#endif
{
return preserveObjectReferences ? attributes.ArraySZSize : -1;
}
private static Assembly ResolveSimpleAssemblyName(AssemblyName assemblyName)
{
return ResolveSimpleAssemblyName(assemblyName.FullName);
}
private static Assembly ResolveSimpleAssemblyName(string assemblyName)
{
Assembly assembly;
if (assemblyName == Globals.MscorlibAssemblyName)
{
assembly = Globals.TypeOfInt.Assembly;
}
else
{
assembly = Assembly.LoadWithPartialName(assemblyName);
if (assembly == null)
{
AssemblyName an = new AssemblyName(assemblyName)
{
Version = null
};
assembly = Assembly.LoadWithPartialName(an.FullName);
}
}
return assembly;
}
private static void CheckTypeForwardedTo(Assembly sourceAssembly, Assembly destinationAssembly, Type resolvedType)
{
if (sourceAssembly != destinationAssembly && !NetDataContractSerializer.UnsafeTypeForwardingEnabled && !sourceAssembly.IsFullyTrusted)
{
// We have a TypeForwardedTo attribute
//if (!destinationAssembly.PermissionSet.IsSubsetOf(sourceAssembly.PermissionSet))
//{
// // We look for a matching TypeForwardedFrom attribute
// TypeInformation typeInfo = NetDataContractSerializer.GetTypeInformation(resolvedType);
// if (typeInfo.HasTypeForwardedFrom)
// {
// Assembly typeForwardedFromAssembly = null;
// try
// {
// // if this Assembly.Load fails, we still want to throw security exception
// typeForwardedFromAssembly = Assembly.Load(typeInfo.AssemblyString);
// }
// catch { }
// if (typeForwardedFromAssembly == sourceAssembly)
// {
// return;
// }
// }
// throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.CannotDeserializeForwardedType, DataContract.GetClrTypeFullName(resolvedType))));
//}
}
}
private sealed class TopLevelAssemblyTypeResolver
{
private readonly Assembly topLevelAssembly;
public TopLevelAssemblyTypeResolver(Assembly topLevelAssembly)
{
this.topLevelAssembly = topLevelAssembly;
}
public Type ResolveType(Assembly assembly, string simpleTypeName, bool ignoreCase)
{
if (assembly == null)
{
assembly = topLevelAssembly;
}
return assembly.GetType(simpleTypeName, false, ignoreCase);
}
}
private class XmlObjectDataContractTypeInfo
{
private readonly Assembly assembly;
private readonly Type type;
public XmlObjectDataContractTypeInfo(Assembly assembly, Type type)
{
this.assembly = assembly;
this.type = type;
}
public Assembly Assembly => assembly;
public Type Type => type;
}
private class XmlObjectDataContractTypeKey
{
private readonly string assemblyName;
private readonly string typeName;
public XmlObjectDataContractTypeKey(string assemblyName, string typeName)
{
this.assemblyName = assemblyName;
this.typeName = typeName;
}
public override bool Equals(object obj)
{
if (object.ReferenceEquals(this, obj))
{
return true;
}
XmlObjectDataContractTypeKey other = obj as XmlObjectDataContractTypeKey;
if (other == null)
{
return false;
}
if (assemblyName != other.assemblyName)
{
return false;
}
if (typeName != other.typeName)
{
return false;
}
return true;
}
public override int GetHashCode()
{
int hashCode = 0;
if (assemblyName != null)
{
hashCode = assemblyName.GetHashCode();
}
if (typeName != null)
{
hashCode ^= typeName.GetHashCode();
}
return hashCode;
}
}
}
}

View File

@@ -0,0 +1,863 @@
using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Security;
using System.Security.Permissions;
using System.Runtime.CompilerServices;
namespace Compat.Runtime.Serialization
{
internal class XmlObjectSerializerWriteContext : XmlObjectSerializerContext
{
private ObjectReferenceStack byValObjectsInScope = new ObjectReferenceStack();
private XmlSerializableWriter xmlSerializableWriter;
private const int depthToCheckCyclicReference = 512;
protected bool preserveObjectReferences;
private ObjectToIdCache serializedObjects;
private bool isGetOnlyCollection;
private readonly bool unsafeTypeForwardingEnabled;
protected bool serializeReadOnlyTypes;
internal static XmlObjectSerializerWriteContext CreateContext(DataContractSerializer serializer, DataContract rootTypeDataContract, System.Runtime.Serialization.DataContractResolver dataContractResolver)
{
return (serializer.PreserveObjectReferences || serializer.DataContractSurrogate != null)
? new XmlObjectSerializerWriteContextComplex(serializer, rootTypeDataContract, dataContractResolver)
: new XmlObjectSerializerWriteContext(serializer, rootTypeDataContract, dataContractResolver);
}
internal static XmlObjectSerializerWriteContext CreateContext(NetDataContractSerializer serializer, Hashtable surrogateDataContracts)
{
return new XmlObjectSerializerWriteContextComplex(serializer, surrogateDataContracts);
}
protected XmlObjectSerializerWriteContext(
DataContractSerializer serializer,
DataContract rootTypeDataContract,
System.Runtime.Serialization.DataContractResolver resolver)
: base(serializer, rootTypeDataContract, resolver)
{
serializeReadOnlyTypes = serializer.SerializeReadOnlyTypes;
// Known types restricts the set of types that can be deserialized
unsafeTypeForwardingEnabled = true;
}
protected XmlObjectSerializerWriteContext(NetDataContractSerializer serializer)
: base(serializer)
{
unsafeTypeForwardingEnabled = NetDataContractSerializer.UnsafeTypeForwardingEnabled;
}
internal XmlObjectSerializerWriteContext(
XmlObjectSerializer serializer,
int maxItemsInObjectGraph,
System.Runtime.Serialization.StreamingContext streamingContext,
bool ignoreExtensionDataObject)
: base(serializer, maxItemsInObjectGraph, streamingContext, ignoreExtensionDataObject)
{
// Known types restricts the set of types that can be deserialized
unsafeTypeForwardingEnabled = true;
}
protected ObjectToIdCache SerializedObjects
{
get
{
if (serializedObjects == null)
{
serializedObjects = new ObjectToIdCache();
}
return serializedObjects;
}
}
internal override bool IsGetOnlyCollection
{
get => isGetOnlyCollection;
set => isGetOnlyCollection = value;
}
internal bool SerializeReadOnlyTypes => serializeReadOnlyTypes;
internal bool UnsafeTypeForwardingEnabled => unsafeTypeForwardingEnabled;
#if USE_REFEMIT
public void StoreIsGetOnlyCollection()
#else
internal void StoreIsGetOnlyCollection()
#endif
{
isGetOnlyCollection = true;
}
public void InternalSerializeReference(XmlWriterDelegator xmlWriter, object obj, bool isDeclaredType, bool writeXsiType, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
{
if (!OnHandleReference(xmlWriter, obj, true /*canContainCyclicReference*/))
{
InternalSerialize(xmlWriter, obj, isDeclaredType, writeXsiType, declaredTypeID, declaredTypeHandle);
}
OnEndHandleReference(xmlWriter, obj, true /*canContainCyclicReference*/);
}
public virtual void InternalSerialize(XmlWriterDelegator xmlWriter, object obj, bool isDeclaredType, bool writeXsiType, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
{
if (writeXsiType)
{
Type declaredType = Globals.TypeOfObject;
SerializeWithXsiType(xmlWriter, obj, Type.GetTypeHandle(obj), null/*type*/, -1, declaredType.TypeHandle, declaredType);
}
else if (isDeclaredType)
{
DataContract contract = GetDataContract(declaredTypeID, declaredTypeHandle);
SerializeWithoutXsiType(contract, xmlWriter, obj, declaredTypeHandle);
}
else
{
RuntimeTypeHandle objTypeHandle = Type.GetTypeHandle(obj);
if (declaredTypeHandle.Equals(objTypeHandle))
{
DataContract dataContract = (declaredTypeID >= 0)
? GetDataContract(declaredTypeID, declaredTypeHandle)
: GetDataContract(declaredTypeHandle, null /*type*/);
SerializeWithoutXsiType(dataContract, xmlWriter, obj, declaredTypeHandle);
}
else
{
SerializeWithXsiType(xmlWriter, obj, objTypeHandle, null /*type*/, declaredTypeID, declaredTypeHandle, Type.GetTypeFromHandle(declaredTypeHandle));
}
}
}
internal void SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, object obj, RuntimeTypeHandle declaredTypeHandle)
{
if (OnHandleIsReference(xmlWriter, dataContract, obj))
{
return;
}
if (dataContract.KnownDataContracts != null)
{
scopedKnownTypes.Push(dataContract.KnownDataContracts);
WriteDataContractValue(dataContract, xmlWriter, obj, declaredTypeHandle);
scopedKnownTypes.Pop();
}
else
{
WriteDataContractValue(dataContract, xmlWriter, obj, declaredTypeHandle);
}
}
internal virtual void SerializeWithXsiTypeAtTopLevel(DataContract dataContract, XmlWriterDelegator xmlWriter, object obj, RuntimeTypeHandle originalDeclaredTypeHandle, Type graphType)
{
bool verifyKnownType = false;
Type declaredType = rootTypeDataContract.OriginalUnderlyingType;
if (declaredType.IsInterface && CollectionDataContract.IsCollectionInterface(declaredType))
{
if (DataContractResolver != null)
{
WriteResolvedTypeInfo(xmlWriter, graphType, declaredType);
}
}
else if (!declaredType.IsArray) //Array covariance is not supported in XSD. If declared type is array do not write xsi:type. Instead write xsi:type for each item
{
verifyKnownType = WriteTypeInfo(xmlWriter, dataContract, rootTypeDataContract);
}
SerializeAndVerifyType(dataContract, xmlWriter, obj, verifyKnownType, originalDeclaredTypeHandle, declaredType);
}
protected virtual void SerializeWithXsiType(XmlWriterDelegator xmlWriter, object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
{
DataContract dataContract;
bool verifyKnownType = false;
if (declaredType.IsInterface && CollectionDataContract.IsCollectionInterface(declaredType))
{
dataContract = GetDataContractSkipValidation(DataContract.GetId(objectTypeHandle), objectTypeHandle, objectType);
if (OnHandleIsReference(xmlWriter, dataContract, obj))
{
return;
}
if (Mode == SerializationMode.SharedType && dataContract.IsValidContract(Mode))
{
dataContract = dataContract.GetValidContract(Mode);
}
else
{
dataContract = GetDataContract(declaredTypeHandle, declaredType);
}
if (!WriteClrTypeInfo(xmlWriter, dataContract) && DataContractResolver != null)
{
if (objectType == null)
{
objectType = Type.GetTypeFromHandle(objectTypeHandle);
}
WriteResolvedTypeInfo(xmlWriter, objectType, declaredType);
}
}
else if (declaredType.IsArray)//Array covariance is not supported in XSD. If declared type is array do not write xsi:type. Instead write xsi:type for each item
{
// A call to OnHandleIsReference is not necessary here -- arrays cannot be IsReference
dataContract = GetDataContract(objectTypeHandle, objectType);
WriteClrTypeInfo(xmlWriter, dataContract);
dataContract = GetDataContract(declaredTypeHandle, declaredType);
}
else
{
dataContract = GetDataContract(objectTypeHandle, objectType);
if (OnHandleIsReference(xmlWriter, dataContract, obj))
{
return;
}
if (!WriteClrTypeInfo(xmlWriter, dataContract))
{
DataContract declaredTypeContract = (declaredTypeID >= 0)
? GetDataContract(declaredTypeID, declaredTypeHandle)
: GetDataContract(declaredTypeHandle, declaredType);
verifyKnownType = WriteTypeInfo(xmlWriter, dataContract, declaredTypeContract);
}
}
SerializeAndVerifyType(dataContract, xmlWriter, obj, verifyKnownType, declaredTypeHandle, declaredType);
}
internal bool OnHandleIsReference(XmlWriterDelegator xmlWriter, DataContract contract, object obj)
{
if (preserveObjectReferences || !contract.IsReference || isGetOnlyCollection)
{
return false;
}
bool isNew = true;
int objectId = SerializedObjects.GetId(obj, ref isNew);
byValObjectsInScope.EnsureSetAsIsReference(obj);
if (isNew)
{
xmlWriter.WriteAttributeString(Globals.SerPrefix, DictionaryGlobals.IdLocalName,
DictionaryGlobals.SerializationNamespace, string.Format(CultureInfo.InvariantCulture, "{0}{1}", "i", objectId));
return false;
}
else
{
xmlWriter.WriteAttributeString(Globals.SerPrefix, DictionaryGlobals.RefLocalName, DictionaryGlobals.SerializationNamespace, string.Format(CultureInfo.InvariantCulture, "{0}{1}", "i", objectId));
return true;
}
}
protected void SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, object obj, bool verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
{
bool knownTypesAddedInCurrentScope = false;
if (dataContract.KnownDataContracts != null)
{
scopedKnownTypes.Push(dataContract.KnownDataContracts);
knownTypesAddedInCurrentScope = true;
}
if (verifyKnownType)
{
if (!IsKnownType(dataContract, declaredType))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.DcTypeNotFoundOnSerialize, DataContract.GetClrTypeFullName(dataContract.UnderlyingType), dataContract.StableName.Name, dataContract.StableName.Namespace)));
}
}
WriteDataContractValue(dataContract, xmlWriter, obj, declaredTypeHandle);
if (knownTypesAddedInCurrentScope)
{
scopedKnownTypes.Pop();
}
}
internal virtual bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, DataContract dataContract)
{
return false;
}
internal virtual bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, Type dataContractType, string clrTypeName, string clrAssemblyName)
{
return false;
}
internal virtual bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, Type dataContractType, System.Runtime.Serialization.SerializationInfo serInfo)
{
return false;
}
public virtual void WriteAnyType(XmlWriterDelegator xmlWriter, object value)
{
xmlWriter.WriteAnyType(value);
}
public virtual void WriteString(XmlWriterDelegator xmlWriter, string value)
{
xmlWriter.WriteString(value);
}
public virtual void WriteString(XmlWriterDelegator xmlWriter, string value, XmlDictionaryString name, XmlDictionaryString ns)
{
if (value == null)
{
WriteNull(xmlWriter, typeof(string), true/*isMemberTypeSerializable*/, name, ns);
}
else
{
xmlWriter.WriteStartElementPrimitive(name, ns);
xmlWriter.WriteString(value);
xmlWriter.WriteEndElementPrimitive();
}
}
public virtual void WriteBase64(XmlWriterDelegator xmlWriter, byte[] value)
{
xmlWriter.WriteBase64(value);
}
public virtual void WriteBase64(XmlWriterDelegator xmlWriter, byte[] value, XmlDictionaryString name, XmlDictionaryString ns)
{
if (value == null)
{
WriteNull(xmlWriter, typeof(byte[]), true/*isMemberTypeSerializable*/, name, ns);
}
else
{
xmlWriter.WriteStartElementPrimitive(name, ns);
xmlWriter.WriteBase64(value);
xmlWriter.WriteEndElementPrimitive();
}
}
public virtual void WriteUri(XmlWriterDelegator xmlWriter, Uri value)
{
xmlWriter.WriteUri(value);
}
public virtual void WriteUri(XmlWriterDelegator xmlWriter, Uri value, XmlDictionaryString name, XmlDictionaryString ns)
{
if (value == null)
{
WriteNull(xmlWriter, typeof(Uri), true/*isMemberTypeSerializable*/, name, ns);
}
else
{
xmlWriter.WriteStartElementPrimitive(name, ns);
xmlWriter.WriteUri(value);
xmlWriter.WriteEndElementPrimitive();
}
}
public virtual void WriteQName(XmlWriterDelegator xmlWriter, XmlQualifiedName value)
{
xmlWriter.WriteQName(value);
}
public virtual void WriteQName(XmlWriterDelegator xmlWriter, XmlQualifiedName value, XmlDictionaryString name, XmlDictionaryString ns)
{
if (value == null)
{
WriteNull(xmlWriter, typeof(XmlQualifiedName), true/*isMemberTypeSerializable*/, name, ns);
}
else
{
if (ns != null && ns.Value != null && ns.Value.Length > 0)
{
xmlWriter.WriteStartElement(Globals.ElementPrefix, name, ns);
}
else
{
xmlWriter.WriteStartElement(name, ns);
}
xmlWriter.WriteQName(value);
xmlWriter.WriteEndElement();
}
}
internal void HandleGraphAtTopLevel(XmlWriterDelegator writer, object obj, DataContract contract)
{
writer.WriteXmlnsAttribute(Globals.XsiPrefix, DictionaryGlobals.SchemaInstanceNamespace);
if (contract.IsISerializable)
{
writer.WriteXmlnsAttribute(Globals.XsdPrefix, DictionaryGlobals.SchemaNamespace);
}
OnHandleReference(writer, obj, true /*canContainReferences*/);
}
internal virtual bool OnHandleReference(XmlWriterDelegator xmlWriter, object obj, bool canContainCyclicReference)
{
if (xmlWriter._depth < depthToCheckCyclicReference)
{
return false;
}
if (canContainCyclicReference)
{
if (byValObjectsInScope.Contains(obj))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.CannotSerializeObjectWithCycles, DataContract.GetClrTypeFullName(obj.GetType()))));
}
byValObjectsInScope.Push(obj);
}
return false;
}
internal virtual void OnEndHandleReference(XmlWriterDelegator xmlWriter, object obj, bool canContainCyclicReference)
{
if (xmlWriter._depth < depthToCheckCyclicReference)
{
return;
}
if (canContainCyclicReference)
{
byValObjectsInScope.Pop(obj);
}
}
public void WriteNull(XmlWriterDelegator xmlWriter, Type memberType, bool isMemberTypeSerializable)
{
CheckIfTypeSerializable(memberType, isMemberTypeSerializable);
WriteNull(xmlWriter);
}
internal void WriteNull(XmlWriterDelegator xmlWriter, Type memberType, bool isMemberTypeSerializable, XmlDictionaryString name, XmlDictionaryString ns)
{
xmlWriter.WriteStartElement(name, ns);
WriteNull(xmlWriter, memberType, isMemberTypeSerializable);
xmlWriter.WriteEndElement();
}
public void IncrementArrayCount(XmlWriterDelegator xmlWriter, Array array)
{
IncrementCollectionCount(xmlWriter, array.GetLength(0));
}
public void IncrementCollectionCount(XmlWriterDelegator xmlWriter, ICollection collection)
{
IncrementCollectionCount(xmlWriter, collection.Count);
}
public void IncrementCollectionCountGeneric<T>(XmlWriterDelegator xmlWriter, ICollection<T> collection)
{
IncrementCollectionCount(xmlWriter, collection.Count);
}
private void IncrementCollectionCount(XmlWriterDelegator xmlWriter, int size)
{
IncrementItemCount(size);
WriteArraySize(xmlWriter, size);
}
internal virtual void WriteArraySize(XmlWriterDelegator xmlWriter, int size)
{
}
public static T GetDefaultValue<T>()
{
return default(T);
}
public static T GetNullableValue<T>(Nullable<T> value) where T : struct
{
// value.Value will throw if hasValue is false
return value.Value;
}
public static void ThrowRequiredMemberMustBeEmitted(string memberName, Type type)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Runtime.Serialization.SerializationException(SR.Format(SR.RequiredMemberMustBeEmitted, memberName, type.FullName)));
}
public static bool GetHasValue<T>(Nullable<T> value) where T : struct
{
return value.HasValue;
}
internal void WriteIXmlSerializable(XmlWriterDelegator xmlWriter, object obj)
{
if (xmlSerializableWriter == null)
{
xmlSerializableWriter = new XmlSerializableWriter();
}
WriteIXmlSerializable(xmlWriter, obj, xmlSerializableWriter);
}
internal static void WriteRootIXmlSerializable(XmlWriterDelegator xmlWriter, object obj)
{
WriteIXmlSerializable(xmlWriter, obj, new XmlSerializableWriter());
}
private static void WriteIXmlSerializable(XmlWriterDelegator xmlWriter, object obj, XmlSerializableWriter xmlSerializableWriter)
{
xmlSerializableWriter.BeginWrite(xmlWriter.Writer, obj);
IXmlSerializable xmlSerializable = obj as IXmlSerializable;
if (xmlSerializable != null)
{
xmlSerializable.WriteXml(xmlSerializableWriter);
}
else
{
XmlElement xmlElement = obj as XmlElement;
if (xmlElement != null)
{
xmlElement.WriteTo(xmlSerializableWriter);
}
else
{
XmlNode[] xmlNodes = obj as XmlNode[];
if (xmlNodes != null)
{
foreach (XmlNode xmlNode in xmlNodes)
{
xmlNode.WriteTo(xmlSerializableWriter);
}
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.UnknownXmlType, DataContract.GetClrTypeFullName(obj.GetType()))));
}
}
}
xmlSerializableWriter.EndWrite();
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal void GetObjectData(
System.Runtime.Serialization.ISerializable obj,
System.Runtime.Serialization.SerializationInfo serInfo,
System.Runtime.Serialization.StreamingContext context)
{
// Demand the serialization formatter permission every time
//Globals.SerializationFormatterPermission.Demand();
obj.GetObjectData(serInfo, context);
}
public void WriteISerializable(XmlWriterDelegator xmlWriter, System.Runtime.Serialization.ISerializable obj)
{
Type objType = obj.GetType();
System.Runtime.Serialization.SerializationInfo serInfo = new System.Runtime.Serialization.SerializationInfo(objType, XmlObjectSerializer.FormatterConverter, !UnsafeTypeForwardingEnabled);
GetObjectData(obj, serInfo, GetStreamingContext());
if (!UnsafeTypeForwardingEnabled && serInfo.AssemblyName == Globals.MscorlibAssemblyName)
{
// Throw if a malicious type tries to set its assembly name to "0" to get deserialized in mscorlib
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ISerializableAssemblyNameSetToZero, DataContract.GetClrTypeFullName(obj.GetType()))));
}
WriteSerializationInfo(xmlWriter, objType, serInfo);
}
internal void WriteSerializationInfo(XmlWriterDelegator xmlWriter, Type objType, System.Runtime.Serialization.SerializationInfo serInfo)
{
if (DataContract.GetClrTypeFullName(objType) != serInfo.FullTypeName)
{
if (DataContractResolver != null)
{
if (ResolveType(serInfo.ObjectType, objType, out XmlDictionaryString typeName, out XmlDictionaryString typeNs))
{
xmlWriter.WriteAttributeQualifiedName(Globals.SerPrefix, DictionaryGlobals.ISerializableFactoryTypeLocalName, DictionaryGlobals.SerializationNamespace, typeName, typeNs);
}
}
else
{
DataContract.GetDefaultStableName(serInfo.FullTypeName, out string typeName, out string typeNs);
xmlWriter.WriteAttributeQualifiedName(Globals.SerPrefix, DictionaryGlobals.ISerializableFactoryTypeLocalName, DictionaryGlobals.SerializationNamespace, DataContract.GetClrTypeString(typeName), DataContract.GetClrTypeString(typeNs));
}
}
WriteClrTypeInfo(xmlWriter, objType, serInfo);
IncrementItemCount(serInfo.MemberCount);
foreach (System.Runtime.Serialization.SerializationEntry serEntry in serInfo)
{
XmlDictionaryString name = DataContract.GetClrTypeString(DataContract.EncodeLocalName(serEntry.Name));
xmlWriter.WriteStartElement(name, DictionaryGlobals.EmptyString);
object obj = serEntry.Value;
if (obj == null)
{
WriteNull(xmlWriter);
}
else
{
InternalSerializeReference(xmlWriter, obj, false /*isDeclaredType*/, false /*writeXsiType*/, -1, Globals.TypeOfObject.TypeHandle);
}
xmlWriter.WriteEndElement();
}
}
public void WriteExtensionData(XmlWriterDelegator xmlWriter, ExtensionDataObject extensionData, int memberIndex)
{
if (IgnoreExtensionDataObject || extensionData == null)
{
return;
}
IList<ExtensionDataMember> members = extensionData.Members;
if (members != null)
{
for (int i = 0; i < extensionData.Members.Count; i++)
{
ExtensionDataMember member = extensionData.Members[i];
if (member.MemberIndex == memberIndex)
{
WriteExtensionDataMember(xmlWriter, member);
}
}
}
}
private void WriteExtensionDataMember(XmlWriterDelegator xmlWriter, ExtensionDataMember member)
{
xmlWriter.WriteStartElement(member.Name, member.Namespace);
IDataNode dataNode = member.Value;
WriteExtensionDataValue(xmlWriter, dataNode);
xmlWriter.WriteEndElement();
}
internal virtual void WriteExtensionDataTypeInfo(XmlWriterDelegator xmlWriter, IDataNode dataNode)
{
if (dataNode.DataContractName != null)
{
WriteTypeInfo(xmlWriter, dataNode.DataContractName, dataNode.DataContractNamespace);
}
WriteClrTypeInfo(xmlWriter, dataNode.DataType, dataNode.ClrTypeName, dataNode.ClrAssemblyName);
}
internal void WriteExtensionDataValue(XmlWriterDelegator xmlWriter, IDataNode dataNode)
{
IncrementItemCount(1);
if (dataNode == null)
{
WriteNull(xmlWriter);
return;
}
if (dataNode.PreservesReferences
&& OnHandleReference(xmlWriter, (dataNode.Value == null ? dataNode : dataNode.Value), true /*canContainCyclicReference*/))
{
return;
}
Type dataType = dataNode.DataType;
if (dataType == Globals.TypeOfClassDataNode)
{
WriteExtensionClassData(xmlWriter, (ClassDataNode)dataNode);
}
else if (dataType == Globals.TypeOfCollectionDataNode)
{
WriteExtensionCollectionData(xmlWriter, (CollectionDataNode)dataNode);
}
else if (dataType == Globals.TypeOfXmlDataNode)
{
WriteExtensionXmlData(xmlWriter, (XmlDataNode)dataNode);
}
else if (dataType == Globals.TypeOfISerializableDataNode)
{
WriteExtensionISerializableData(xmlWriter, (ISerializableDataNode)dataNode);
}
else
{
WriteExtensionDataTypeInfo(xmlWriter, dataNode);
if (dataType == Globals.TypeOfObject)
{
// NOTE: serialize value in DataNode<object> since it may contain non-primitive
// deserialized object (ex. empty class)
object o = dataNode.Value;
if (o != null)
{
InternalSerialize(xmlWriter, o, false /*isDeclaredType*/, false /*writeXsiType*/, -1, o.GetType().TypeHandle);
}
}
else
{
xmlWriter.WriteExtensionData(dataNode);
}
}
if (dataNode.PreservesReferences)
{
OnEndHandleReference(xmlWriter, (dataNode.Value == null ? dataNode : dataNode.Value), true /*canContainCyclicReference*/);
}
}
internal bool TryWriteDeserializedExtensionData(XmlWriterDelegator xmlWriter, IDataNode dataNode)
{
object o = dataNode.Value;
if (o == null)
{
return false;
}
Type declaredType = (dataNode.DataContractName == null) ? o.GetType() : Globals.TypeOfObject;
InternalSerialize(xmlWriter, o, false /*isDeclaredType*/, false /*writeXsiType*/, -1, declaredType.TypeHandle);
return true;
}
private void WriteExtensionClassData(XmlWriterDelegator xmlWriter, ClassDataNode dataNode)
{
if (!TryWriteDeserializedExtensionData(xmlWriter, dataNode))
{
WriteExtensionDataTypeInfo(xmlWriter, dataNode);
IList<ExtensionDataMember> members = dataNode.Members;
if (members != null)
{
for (int i = 0; i < members.Count; i++)
{
WriteExtensionDataMember(xmlWriter, members[i]);
}
}
}
}
private void WriteExtensionCollectionData(XmlWriterDelegator xmlWriter, CollectionDataNode dataNode)
{
if (!TryWriteDeserializedExtensionData(xmlWriter, dataNode))
{
WriteExtensionDataTypeInfo(xmlWriter, dataNode);
WriteArraySize(xmlWriter, dataNode.Size);
IList<IDataNode> items = dataNode.Items;
if (items != null)
{
for (int i = 0; i < items.Count; i++)
{
xmlWriter.WriteStartElement(dataNode.ItemName, dataNode.ItemNamespace);
WriteExtensionDataValue(xmlWriter, items[i]);
xmlWriter.WriteEndElement();
}
}
}
}
private void WriteExtensionISerializableData(XmlWriterDelegator xmlWriter, ISerializableDataNode dataNode)
{
if (!TryWriteDeserializedExtensionData(xmlWriter, dataNode))
{
WriteExtensionDataTypeInfo(xmlWriter, dataNode);
if (dataNode.FactoryTypeName != null)
{
xmlWriter.WriteAttributeQualifiedName(Globals.SerPrefix, DictionaryGlobals.ISerializableFactoryTypeLocalName, DictionaryGlobals.SerializationNamespace, dataNode.FactoryTypeName, dataNode.FactoryTypeNamespace);
}
IList<ISerializableDataMember> members = dataNode.Members;
if (members != null)
{
for (int i = 0; i < members.Count; i++)
{
ISerializableDataMember member = members[i];
xmlWriter.WriteStartElement(member.Name, string.Empty);
WriteExtensionDataValue(xmlWriter, member.Value);
xmlWriter.WriteEndElement();
}
}
}
}
private void WriteExtensionXmlData(XmlWriterDelegator xmlWriter, XmlDataNode dataNode)
{
if (!TryWriteDeserializedExtensionData(xmlWriter, dataNode))
{
IList<XmlAttribute> xmlAttributes = dataNode.XmlAttributes;
if (xmlAttributes != null)
{
foreach (XmlAttribute attribute in xmlAttributes)
{
attribute.WriteTo(xmlWriter.Writer);
}
}
WriteExtensionDataTypeInfo(xmlWriter, dataNode);
IList<XmlNode> xmlChildNodes = dataNode.XmlChildNodes;
if (xmlChildNodes != null)
{
foreach (XmlNode node in xmlChildNodes)
{
node.WriteTo(xmlWriter.Writer);
}
}
}
}
protected virtual void WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, object obj, RuntimeTypeHandle declaredTypeHandle)
{
dataContract.WriteXmlValue(xmlWriter, obj, this);
}
protected virtual void WriteNull(XmlWriterDelegator xmlWriter)
{
XmlObjectSerializer.WriteNull(xmlWriter);
}
private void WriteResolvedTypeInfo(XmlWriterDelegator writer, Type objectType, Type declaredType)
{
if (ResolveType(objectType, declaredType, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace))
{
WriteTypeInfo(writer, typeName, typeNamespace);
}
}
private bool ResolveType(Type objectType, Type declaredType, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
{
if (!DataContractResolver.TryResolveType(objectType, declaredType, KnownTypeResolver, out typeName, out typeNamespace))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ResolveTypeReturnedFalse, DataContract.GetClrTypeFullName(DataContractResolver.GetType()), DataContract.GetClrTypeFullName(objectType))));
}
if (typeName == null)
{
if (typeNamespace == null)
{
return false;
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ResolveTypeReturnedNull, DataContract.GetClrTypeFullName(DataContractResolver.GetType()), DataContract.GetClrTypeFullName(objectType))));
}
}
if (typeNamespace == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ResolveTypeReturnedNull, DataContract.GetClrTypeFullName(DataContractResolver.GetType()), DataContract.GetClrTypeFullName(objectType))));
}
return true;
}
protected virtual bool WriteTypeInfo(XmlWriterDelegator writer, DataContract contract, DataContract declaredContract)
{
if (!XmlObjectSerializer.IsContractDeclared(contract, declaredContract))
{
if (DataContractResolver == null)
{
WriteTypeInfo(writer, contract.Name, contract.Namespace);
return true;
}
else
{
WriteResolvedTypeInfo(writer, contract.OriginalUnderlyingType, declaredContract.OriginalUnderlyingType);
return false;
}
}
return false;
}
protected virtual void WriteTypeInfo(XmlWriterDelegator writer, string dataContractName, string dataContractNamespace)
{
writer.WriteAttributeQualifiedName(Globals.XsiPrefix, DictionaryGlobals.XsiTypeLocalName, DictionaryGlobals.SchemaInstanceNamespace, dataContractName, dataContractNamespace);
}
protected virtual void WriteTypeInfo(XmlWriterDelegator writer, XmlDictionaryString dataContractName, XmlDictionaryString dataContractNamespace)
{
writer.WriteAttributeQualifiedName(Globals.XsiPrefix, DictionaryGlobals.XsiTypeLocalName, DictionaryGlobals.SchemaInstanceNamespace, dataContractName, dataContractNamespace);
}
}
}

View File

@@ -0,0 +1,406 @@
using System;
using System.Collections;
using System.Runtime.CompilerServices;
using System.Xml;
using DataContractResolver = System.Runtime.Serialization.DataContractResolver;
using InvalidDataContractException = System.Runtime.Serialization.InvalidDataContractException;
using ISurrogateSelector = System.Runtime.Serialization.ISurrogateSelector;
using SerializationBinder = System.Runtime.Serialization.SerializationBinder;
using SerializationInfo = System.Runtime.Serialization.SerializationInfo;
using StreamingContext = System.Runtime.Serialization.StreamingContext;
namespace Compat.Runtime.Serialization
{
internal class XmlObjectSerializerWriteContextComplex : XmlObjectSerializerWriteContext
{
protected IDataContractSurrogate dataContractSurrogate;
private readonly SerializationMode mode;
private readonly SerializationBinder binder;
private readonly ISurrogateSelector surrogateSelector;
private StreamingContext streamingContext;
private Hashtable surrogateDataContracts;
internal XmlObjectSerializerWriteContextComplex(
DataContractSerializer serializer,
DataContract rootTypeDataContract,
DataContractResolver dataContractResolver)
: base(serializer, rootTypeDataContract, dataContractResolver)
{
mode = SerializationMode.SharedContract;
preserveObjectReferences = serializer.PreserveObjectReferences;
dataContractSurrogate = serializer.DataContractSurrogate;
}
internal XmlObjectSerializerWriteContextComplex(NetDataContractSerializer serializer, Hashtable surrogateDataContracts)
: base(serializer)
{
mode = SerializationMode.SharedType;
preserveObjectReferences = true;
streamingContext = serializer.Context;
binder = serializer.Binder;
surrogateSelector = serializer.SurrogateSelector;
this.surrogateDataContracts = surrogateDataContracts;
}
internal XmlObjectSerializerWriteContextComplex(XmlObjectSerializer serializer, int maxItemsInObjectGraph, StreamingContext streamingContext, bool ignoreExtensionDataObject)
: base(serializer, maxItemsInObjectGraph, streamingContext, ignoreExtensionDataObject)
{
}
internal override SerializationMode Mode => mode;
internal override DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
{
DataContract dataContract = null;
if (mode == SerializationMode.SharedType && surrogateSelector != null)
{
dataContract = NetDataContractSerializer.GetDataContractFromSurrogateSelector(surrogateSelector, streamingContext, typeHandle, type, ref surrogateDataContracts);
}
if (dataContract != null)
{
if (IsGetOnlyCollection && dataContract is SurrogateDataContract)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
}
return dataContract;
}
return base.GetDataContract(typeHandle, type);
}
internal override DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
{
DataContract dataContract = null;
if (mode == SerializationMode.SharedType && surrogateSelector != null)
{
dataContract = NetDataContractSerializer.GetDataContractFromSurrogateSelector(surrogateSelector, streamingContext, typeHandle, null /*type*/, ref surrogateDataContracts);
}
if (dataContract != null)
{
if (IsGetOnlyCollection && dataContract is SurrogateDataContract)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
}
return dataContract;
}
return base.GetDataContract(id, typeHandle);
}
internal override DataContract GetDataContractSkipValidation(int typeId, RuntimeTypeHandle typeHandle, Type type)
{
DataContract dataContract = null;
if (mode == SerializationMode.SharedType && surrogateSelector != null)
{
dataContract = NetDataContractSerializer.GetDataContractFromSurrogateSelector(surrogateSelector, streamingContext, typeHandle, null /*type*/, ref surrogateDataContracts);
}
if (dataContract != null)
{
if (IsGetOnlyCollection && dataContract is SurrogateDataContract)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
}
return dataContract;
}
return base.GetDataContractSkipValidation(typeId, typeHandle, type);
}
internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, DataContract dataContract)
{
if (mode == SerializationMode.SharedType)
{
NetDataContractSerializer.WriteClrTypeInfo(xmlWriter, dataContract, binder);
return true;
}
return false;
}
internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, Type dataContractType, string clrTypeName, string clrAssemblyName)
{
if (mode == SerializationMode.SharedType)
{
NetDataContractSerializer.WriteClrTypeInfo(xmlWriter, dataContractType, binder, clrTypeName, clrAssemblyName);
return true;
}
return false;
}
internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, Type dataContractType, SerializationInfo serInfo)
{
if (mode == SerializationMode.SharedType)
{
NetDataContractSerializer.WriteClrTypeInfo(xmlWriter, dataContractType, binder, serInfo);
return true;
}
return false;
}
public override void WriteAnyType(XmlWriterDelegator xmlWriter, object value)
{
if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
{
xmlWriter.WriteAnyType(value);
}
}
public override void WriteString(XmlWriterDelegator xmlWriter, string value)
{
if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
{
xmlWriter.WriteString(value);
}
}
public override void WriteString(XmlWriterDelegator xmlWriter, string value, XmlDictionaryString name, XmlDictionaryString ns)
{
if (value == null)
{
WriteNull(xmlWriter, typeof(string), true/*isMemberTypeSerializable*/, name, ns);
}
else
{
xmlWriter.WriteStartElementPrimitive(name, ns);
if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
{
xmlWriter.WriteString(value);
}
xmlWriter.WriteEndElementPrimitive();
}
}
public override void WriteBase64(XmlWriterDelegator xmlWriter, byte[] value)
{
if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
{
xmlWriter.WriteBase64(value);
}
}
public override void WriteBase64(XmlWriterDelegator xmlWriter, byte[] value, XmlDictionaryString name, XmlDictionaryString ns)
{
if (value == null)
{
WriteNull(xmlWriter, typeof(byte[]), true/*isMemberTypeSerializable*/, name, ns);
}
else
{
xmlWriter.WriteStartElementPrimitive(name, ns);
if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
{
xmlWriter.WriteBase64(value);
}
xmlWriter.WriteEndElementPrimitive();
}
}
public override void WriteUri(XmlWriterDelegator xmlWriter, Uri value)
{
if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
{
xmlWriter.WriteUri(value);
}
}
public override void WriteUri(XmlWriterDelegator xmlWriter, Uri value, XmlDictionaryString name, XmlDictionaryString ns)
{
if (value == null)
{
WriteNull(xmlWriter, typeof(Uri), true/*isMemberTypeSerializable*/, name, ns);
}
else
{
xmlWriter.WriteStartElementPrimitive(name, ns);
if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
{
xmlWriter.WriteUri(value);
}
xmlWriter.WriteEndElementPrimitive();
}
}
public override void WriteQName(XmlWriterDelegator xmlWriter, XmlQualifiedName value)
{
if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
{
xmlWriter.WriteQName(value);
}
}
public override void WriteQName(XmlWriterDelegator xmlWriter, XmlQualifiedName value, XmlDictionaryString name, XmlDictionaryString ns)
{
if (value == null)
{
WriteNull(xmlWriter, typeof(XmlQualifiedName), true/*isMemberTypeSerializable*/, name, ns);
}
else
{
if (ns != null && ns.Value != null && ns.Value.Length > 0)
{
xmlWriter.WriteStartElement(Globals.ElementPrefix, name, ns);
}
else
{
xmlWriter.WriteStartElement(name, ns);
}
if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
{
xmlWriter.WriteQName(value);
}
xmlWriter.WriteEndElement();
}
}
public override void InternalSerialize(XmlWriterDelegator xmlWriter, object obj, bool isDeclaredType, bool writeXsiType, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
{
if (dataContractSurrogate == null)
{
base.InternalSerialize(xmlWriter, obj, isDeclaredType, writeXsiType, declaredTypeID, declaredTypeHandle);
}
else
{
InternalSerializeWithSurrogate(xmlWriter, obj, isDeclaredType, writeXsiType, declaredTypeID, declaredTypeHandle);
}
}
internal override bool OnHandleReference(XmlWriterDelegator xmlWriter, object obj, bool canContainCyclicReference)
{
if (preserveObjectReferences && !IsGetOnlyCollection)
{
bool isNew = true;
int objectId = SerializedObjects.GetId(obj, ref isNew);
if (isNew)
{
xmlWriter.WriteAttributeInt(Globals.SerPrefix, DictionaryGlobals.IdLocalName, DictionaryGlobals.SerializationNamespace, objectId);
}
else
{
xmlWriter.WriteAttributeInt(Globals.SerPrefix, DictionaryGlobals.RefLocalName, DictionaryGlobals.SerializationNamespace, objectId);
xmlWriter.WriteAttributeBool(Globals.XsiPrefix, DictionaryGlobals.XsiNilLocalName, DictionaryGlobals.SchemaInstanceNamespace, true);
}
return !isNew;
}
return base.OnHandleReference(xmlWriter, obj, canContainCyclicReference);
}
internal override void OnEndHandleReference(XmlWriterDelegator xmlWriter, object obj, bool canContainCyclicReference)
{
if (preserveObjectReferences && !IsGetOnlyCollection)
{
return;
}
base.OnEndHandleReference(xmlWriter, obj, canContainCyclicReference);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private bool CheckIfTypeSerializableForSharedTypeMode(Type memberType)
{
Fx.Assert(surrogateSelector != null, "Method should not be called when surrogateSelector is null.");
return (surrogateSelector.GetSurrogate(memberType, streamingContext, out ISurrogateSelector surrogateSelectorNotUsed) != null);
}
internal override void CheckIfTypeSerializable(Type memberType, bool isMemberTypeSerializable)
{
if (mode == SerializationMode.SharedType && surrogateSelector != null &&
CheckIfTypeSerializableForSharedTypeMode(memberType))
{
return;
}
else
{
if (dataContractSurrogate != null)
{
while (memberType.IsArray)
{
memberType = memberType.GetElementType();
}
memberType = DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, memberType);
if (!DataContract.IsTypeSerializable(memberType))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.TypeNotSerializable, memberType)));
}
return;
}
}
base.CheckIfTypeSerializable(memberType, isMemberTypeSerializable);
}
internal override Type GetSurrogatedType(Type type)
{
if (dataContractSurrogate == null)
{
return base.GetSurrogatedType(type);
}
else
{
type = DataContract.UnwrapNullableType(type);
Type surrogateType = DataContractSerializer.GetSurrogatedType(dataContractSurrogate, type);
if (IsGetOnlyCollection && surrogateType != type)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
DataContract.GetClrTypeFullName(type))));
}
else
{
return surrogateType;
}
}
}
private void InternalSerializeWithSurrogate(XmlWriterDelegator xmlWriter, object obj, bool isDeclaredType, bool writeXsiType, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
{
RuntimeTypeHandle objTypeHandle = isDeclaredType ? declaredTypeHandle : Type.GetTypeHandle(obj);
object oldObj = obj;
int objOldId = 0;
Type objType = Type.GetTypeFromHandle(objTypeHandle);
Type declaredType = GetSurrogatedType(Type.GetTypeFromHandle(declaredTypeHandle));
declaredTypeHandle = declaredType.TypeHandle;
obj = DataContractSerializer.SurrogateToDataContractType(dataContractSurrogate, obj, declaredType, ref objType);
objTypeHandle = objType.TypeHandle;
if (oldObj != obj)
{
objOldId = SerializedObjects.ReassignId(0, oldObj, obj);
}
if (writeXsiType)
{
declaredType = Globals.TypeOfObject;
SerializeWithXsiType(xmlWriter, obj, objTypeHandle, objType, -1, declaredType.TypeHandle, declaredType);
}
else if (declaredTypeHandle.Equals(objTypeHandle))
{
DataContract contract = GetDataContract(objTypeHandle, objType);
SerializeWithoutXsiType(contract, xmlWriter, obj, declaredTypeHandle);
}
else
{
SerializeWithXsiType(xmlWriter, obj, objTypeHandle, objType, -1, declaredTypeHandle, declaredType);
}
if (oldObj != obj)
{
SerializedObjects.ReassignId(objOldId, obj, oldObj);
}
}
internal override void WriteArraySize(XmlWriterDelegator xmlWriter, int size)
{
if (preserveObjectReferences && size > -1)
{
xmlWriter.WriteAttributeInt(Globals.SerPrefix, DictionaryGlobals.ArraySizeLocalName, DictionaryGlobals.SerializationNamespace, size);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,199 @@
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace Compat.Runtime.Serialization
{
internal class XmlSerializableReader : XmlReader, IXmlLineInfo, IXmlTextParser
{
private XmlReaderDelegator xmlReader;
private int startDepth;
private bool isRootEmptyElement;
private XmlReader innerReader;
private XmlReader InnerReader => innerReader;
internal void BeginRead(XmlReaderDelegator xmlReader)
{
if (xmlReader.NodeType != XmlNodeType.Element)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializerReadContext.CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
}
this.xmlReader = xmlReader;
startDepth = xmlReader.Depth;
innerReader = xmlReader.UnderlyingReader;
isRootEmptyElement = InnerReader.IsEmptyElement;
}
internal void EndRead()
{
if (isRootEmptyElement)
{
xmlReader.Read();
}
else
{
if (xmlReader.IsStartElement() && xmlReader.Depth == startDepth)
{
xmlReader.Read();
}
while (xmlReader.Depth > startDepth)
{
if (!xmlReader.Read())
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializerReadContext.CreateUnexpectedStateException(XmlNodeType.EndElement, xmlReader));
}
}
}
}
public override bool Read()
{
XmlReader reader = InnerReader;
if (reader.Depth == startDepth)
{
if (reader.NodeType == XmlNodeType.EndElement ||
(reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement))
{
return false;
}
}
return reader.Read();
}
public override void Close()
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.IXmlSerializableIllegalOperation));
}
public override XmlReaderSettings Settings => InnerReader.Settings;
public override XmlNodeType NodeType => InnerReader.NodeType;
public override string Name => InnerReader.Name;
public override string LocalName => InnerReader.LocalName;
public override string NamespaceURI => InnerReader.NamespaceURI;
public override string Prefix => InnerReader.Prefix;
public override bool HasValue => InnerReader.HasValue;
public override string Value => InnerReader.Value;
public override int Depth => InnerReader.Depth;
public override string BaseURI => InnerReader.BaseURI;
public override bool IsEmptyElement => InnerReader.IsEmptyElement;
public override bool IsDefault => InnerReader.IsDefault;
public override char QuoteChar => InnerReader.QuoteChar;
public override XmlSpace XmlSpace => InnerReader.XmlSpace;
public override string XmlLang => InnerReader.XmlLang;
public override IXmlSchemaInfo SchemaInfo => InnerReader.SchemaInfo;
public override Type ValueType => InnerReader.ValueType;
public override int AttributeCount => InnerReader.AttributeCount;
public override string this[int i] => InnerReader[i];
public override string this[string name] => InnerReader[name];
public override string this[string name, string namespaceURI] => InnerReader[name, namespaceURI];
public override bool EOF => InnerReader.EOF;
public override ReadState ReadState => InnerReader.ReadState;
public override XmlNameTable NameTable => InnerReader.NameTable;
public override bool CanResolveEntity => InnerReader.CanResolveEntity;
public override bool CanReadBinaryContent => InnerReader.CanReadBinaryContent;
public override bool CanReadValueChunk => InnerReader.CanReadValueChunk;
public override bool HasAttributes => InnerReader.HasAttributes;
public override string GetAttribute(string name) { return InnerReader.GetAttribute(name); }
public override string GetAttribute(string name, string namespaceURI) { return InnerReader.GetAttribute(name, namespaceURI); }
public override string GetAttribute(int i) { return InnerReader.GetAttribute(i); }
public override bool MoveToAttribute(string name) { return InnerReader.MoveToAttribute(name); }
public override bool MoveToAttribute(string name, string ns) { return InnerReader.MoveToAttribute(name, ns); }
public override void MoveToAttribute(int i) { InnerReader.MoveToAttribute(i); }
public override bool MoveToFirstAttribute() { return InnerReader.MoveToFirstAttribute(); }
public override bool MoveToNextAttribute() { return InnerReader.MoveToNextAttribute(); }
public override bool MoveToElement() { return InnerReader.MoveToElement(); }
public override string LookupNamespace(string prefix) { return InnerReader.LookupNamespace(prefix); }
public override bool ReadAttributeValue() { return InnerReader.ReadAttributeValue(); }
public override void ResolveEntity() { InnerReader.ResolveEntity(); }
public override bool IsStartElement() { return InnerReader.IsStartElement(); }
public override bool IsStartElement(string name) { return InnerReader.IsStartElement(name); }
public override bool IsStartElement(string localname, string ns) { return InnerReader.IsStartElement(localname, ns); }
public override XmlNodeType MoveToContent() { return InnerReader.MoveToContent(); }
public override object ReadContentAsObject() { return InnerReader.ReadContentAsObject(); }
public override bool ReadContentAsBoolean() { return InnerReader.ReadContentAsBoolean(); }
public override DateTime ReadContentAsDateTime() { return InnerReader.ReadContentAsDateTime(); }
public override double ReadContentAsDouble() { return InnerReader.ReadContentAsDouble(); }
public override int ReadContentAsInt() { return InnerReader.ReadContentAsInt(); }
public override long ReadContentAsLong() { return InnerReader.ReadContentAsLong(); }
public override string ReadContentAsString() { return InnerReader.ReadContentAsString(); }
public override object ReadContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver) { return InnerReader.ReadContentAs(returnType, namespaceResolver); }
public override int ReadContentAsBase64(byte[] buffer, int index, int count) { return InnerReader.ReadContentAsBase64(buffer, index, count); }
public override int ReadContentAsBinHex(byte[] buffer, int index, int count) { return InnerReader.ReadContentAsBinHex(buffer, index, count); }
public override int ReadValueChunk(char[] buffer, int index, int count) { return InnerReader.ReadValueChunk(buffer, index, count); }
public override string ReadString() { return InnerReader.ReadString(); }
// IXmlTextParser members
bool IXmlTextParser.Normalized
{
get
{
IXmlTextParser xmlTextParser = InnerReader as IXmlTextParser;
return (xmlTextParser == null) ? xmlReader.Normalized : xmlTextParser.Normalized;
}
set
{
IXmlTextParser xmlTextParser = InnerReader as IXmlTextParser;
if (xmlTextParser == null)
{
xmlReader.Normalized = value;
}
else
{
xmlTextParser.Normalized = value;
}
}
}
WhitespaceHandling IXmlTextParser.WhitespaceHandling
{
get
{
IXmlTextParser xmlTextParser = InnerReader as IXmlTextParser;
return (xmlTextParser == null) ? xmlReader.WhitespaceHandling : xmlTextParser.WhitespaceHandling;
}
set
{
IXmlTextParser xmlTextParser = InnerReader as IXmlTextParser;
if (xmlTextParser == null)
{
xmlReader.WhitespaceHandling = value;
}
else
{
xmlTextParser.WhitespaceHandling = value;
}
}
}
// IXmlLineInfo members
bool IXmlLineInfo.HasLineInfo()
{
IXmlLineInfo xmlLineInfo = InnerReader as IXmlLineInfo;
return (xmlLineInfo == null) ? xmlReader.HasLineInfo() : xmlLineInfo.HasLineInfo();
}
int IXmlLineInfo.LineNumber
{
get
{
IXmlLineInfo xmlLineInfo = InnerReader as IXmlLineInfo;
return (xmlLineInfo == null) ? xmlReader.LineNumber : xmlLineInfo.LineNumber;
}
}
int IXmlLineInfo.LinePosition
{
get
{
IXmlLineInfo xmlLineInfo = InnerReader as IXmlLineInfo;
return (xmlLineInfo == null) ? xmlReader.LinePosition : xmlLineInfo.LinePosition;
}
}
}
}

View File

@@ -0,0 +1,109 @@
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal class XmlSerializableWriter : XmlWriter
{
private XmlWriter _xmlWriter;
private int _depth = 0;
private object _obj;
internal void BeginWrite(XmlWriter xmlWriter, object obj)
{
_depth = 0;
_xmlWriter = xmlWriter;
_obj = obj;
}
internal void EndWrite()
{
if (_depth != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.IXmlSerializableMissingEndElements, (_obj == null ? string.Empty : DataContract.GetClrTypeFullName(_obj.GetType())))));
}
_obj = null;
}
public override void WriteStartDocument()
{
if (WriteState == WriteState.Start)
{
_xmlWriter.WriteStartDocument();
}
}
public override void WriteEndDocument() { _xmlWriter.WriteEndDocument(); }
public override void WriteStartDocument(bool standalone)
{
if (WriteState == WriteState.Start)
{
_xmlWriter.WriteStartDocument(standalone);
}
}
public override void WriteDocType(string name, string pubid, string sysid, string subset)
{
// XmlSerializer does not write doc type
}
public override void WriteStartElement(string prefix, string localName, string ns)
{
_xmlWriter.WriteStartElement(prefix, localName, ns);
_depth++;
}
public override void WriteEndElement()
{
if (_depth == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.IXmlSerializableWritePastSubTree, (_obj == null ? string.Empty : DataContract.GetClrTypeFullName(_obj.GetType())))));
}
_xmlWriter.WriteEndElement();
_depth--;
}
public override void WriteFullEndElement()
{
if (_depth == 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.IXmlSerializableWritePastSubTree, (_obj == null ? string.Empty : DataContract.GetClrTypeFullName(_obj.GetType())))));
}
_xmlWriter.WriteFullEndElement();
_depth--;
}
public override void Close()
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.IXmlSerializableIllegalOperation));
}
public override void WriteStartAttribute(string prefix, string localName, string ns)
{
_xmlWriter.WriteStartAttribute(prefix, localName, ns);
}
public override void WriteEndAttribute() { _xmlWriter.WriteEndAttribute(); }
public override void WriteCData(string text) { _xmlWriter.WriteCData(text); }
public override void WriteComment(string text) { _xmlWriter.WriteComment(text); }
public override void WriteProcessingInstruction(string name, string text) { _xmlWriter.WriteProcessingInstruction(name, text); }
public override void WriteEntityRef(string name) { _xmlWriter.WriteEntityRef(name); }
public override void WriteCharEntity(char ch) { _xmlWriter.WriteCharEntity(ch); }
public override void WriteWhitespace(string ws) { _xmlWriter.WriteWhitespace(ws); }
public override void WriteString(string text) { _xmlWriter.WriteString(text); }
public override void WriteSurrogateCharEntity(char lowChar, char highChar) { _xmlWriter.WriteSurrogateCharEntity(lowChar, highChar); }
public override void WriteChars(char[] buffer, int index, int count) { _xmlWriter.WriteChars(buffer, index, count); }
public override void WriteRaw(char[] buffer, int index, int count) { _xmlWriter.WriteRaw(buffer, index, count); }
public override void WriteRaw(string data) { _xmlWriter.WriteRaw(data); }
public override void WriteBase64(byte[] buffer, int index, int count) { _xmlWriter.WriteBase64(buffer, index, count); }
public override void WriteBinHex(byte[] buffer, int index, int count) { _xmlWriter.WriteBinHex(buffer, index, count); }
public override WriteState WriteState => _xmlWriter.WriteState;
public override void Flush() { _xmlWriter.Flush(); }
public override void WriteName(string name) { _xmlWriter.WriteName(name); }
public override void WriteQualifiedName(string localName, string ns) { _xmlWriter.WriteQualifiedName(localName, ns); }
public override string LookupPrefix(string ns) { return _xmlWriter.LookupPrefix(ns); }
public override XmlSpace XmlSpace => _xmlWriter.XmlSpace;
public override string XmlLang => _xmlWriter.XmlLang;
public override void WriteNmToken(string name) { _xmlWriter.WriteNmToken(name); }
}
}

View File

@@ -0,0 +1,812 @@
using System;
using System.Globalization;
using System.Xml;
namespace Compat.Runtime.Serialization
{
internal class XmlWriterDelegator
{
protected XmlWriter _writer;
protected XmlDictionaryWriter _dictionaryWriter;
internal int _depth;
private int _prefixes;
public XmlWriterDelegator(XmlWriter writer)
{
_writer = writer ?? throw new ArgumentNullException(nameof(writer));
_dictionaryWriter = writer as XmlDictionaryWriter;
}
internal XmlWriter Writer => _writer;
internal void Flush()
{
_writer.Flush();
}
internal string LookupPrefix(string ns)
{
return _writer.LookupPrefix(ns);
}
private void WriteEndAttribute()
{
_writer.WriteEndAttribute();
}
public void WriteEndElement()
{
_writer.WriteEndElement();
_depth--;
}
internal void WriteRaw(char[] buffer, int index, int count)
{
_writer.WriteRaw(buffer, index, count);
}
internal void WriteRaw(string data)
{
_writer.WriteRaw(data);
}
internal void WriteXmlnsAttribute(XmlDictionaryString ns)
{
if (_dictionaryWriter != null)
{
if (ns != null)
{
_dictionaryWriter.WriteXmlnsAttribute(null, ns);
}
}
else
{
WriteXmlnsAttribute(ns.Value);
}
}
internal void WriteXmlnsAttribute(string ns)
{
if (ns != null)
{
if (ns.Length == 0)
{
_writer.WriteAttributeString("xmlns", string.Empty, null, ns);
}
else
{
if (_dictionaryWriter != null)
{
_dictionaryWriter.WriteXmlnsAttribute(null, ns);
}
else
{
string prefix = _writer.LookupPrefix(ns);
if (prefix == null)
{
prefix = string.Format(CultureInfo.InvariantCulture, "d{0}p{1}", _depth, _prefixes);
_prefixes++;
_writer.WriteAttributeString("xmlns", prefix, null, ns);
}
}
}
}
}
internal void WriteXmlnsAttribute(string prefix, XmlDictionaryString ns)
{
if (_dictionaryWriter != null)
{
_dictionaryWriter.WriteXmlnsAttribute(prefix, ns);
}
else
{
_writer.WriteAttributeString("xmlns", prefix, null, ns.Value);
}
}
private void WriteStartAttribute(string prefix, string localName, string ns)
{
_writer.WriteStartAttribute(prefix, localName, ns);
}
private void WriteStartAttribute(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri)
{
if (_dictionaryWriter != null)
{
_dictionaryWriter.WriteStartAttribute(prefix, localName, namespaceUri);
}
else
{
_writer.WriteStartAttribute(prefix,
(localName == null ? null : localName.Value),
(namespaceUri == null ? null : namespaceUri.Value));
}
}
internal void WriteAttributeString(string prefix, string localName, string ns, string value)
{
WriteStartAttribute(prefix, localName, ns);
WriteAttributeStringValue(value);
WriteEndAttribute();
}
internal void WriteAttributeString(string prefix, XmlDictionaryString attrName, XmlDictionaryString attrNs, string value)
{
WriteStartAttribute(prefix, attrName, attrNs);
WriteAttributeStringValue(value);
WriteEndAttribute();
}
private void WriteAttributeStringValue(string value)
{
_writer.WriteValue(value);
}
internal void WriteAttributeString(string prefix, XmlDictionaryString attrName, XmlDictionaryString attrNs, XmlDictionaryString value)
{
WriteStartAttribute(prefix, attrName, attrNs);
WriteAttributeStringValue(value);
WriteEndAttribute();
}
private void WriteAttributeStringValue(XmlDictionaryString value)
{
if (_dictionaryWriter == null)
{
_writer.WriteString(value.Value);
}
else
{
_dictionaryWriter.WriteString(value);
}
}
internal void WriteAttributeInt(string prefix, XmlDictionaryString attrName, XmlDictionaryString attrNs, int value)
{
WriteStartAttribute(prefix, attrName, attrNs);
WriteAttributeIntValue(value);
WriteEndAttribute();
}
private void WriteAttributeIntValue(int value)
{
_writer.WriteValue(value);
}
internal void WriteAttributeBool(string prefix, XmlDictionaryString attrName, XmlDictionaryString attrNs, bool value)
{
WriteStartAttribute(prefix, attrName, attrNs);
WriteAttributeBoolValue(value);
WriteEndAttribute();
}
private void WriteAttributeBoolValue(bool value)
{
_writer.WriteValue(value);
}
internal void WriteAttributeQualifiedName(string attrPrefix, XmlDictionaryString attrName, XmlDictionaryString attrNs, string name, string ns)
{
WriteXmlnsAttribute(ns);
WriteStartAttribute(attrPrefix, attrName, attrNs);
WriteAttributeQualifiedNameValue(name, ns);
WriteEndAttribute();
}
private void WriteAttributeQualifiedNameValue(string name, string ns)
{
_writer.WriteQualifiedName(name, ns);
}
internal void WriteAttributeQualifiedName(string attrPrefix, XmlDictionaryString attrName, XmlDictionaryString attrNs, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteXmlnsAttribute(ns);
WriteStartAttribute(attrPrefix, attrName, attrNs);
WriteAttributeQualifiedNameValue(name, ns);
WriteEndAttribute();
}
private void WriteAttributeQualifiedNameValue(XmlDictionaryString name, XmlDictionaryString ns)
{
if (_dictionaryWriter == null)
{
_writer.WriteQualifiedName(name.Value, ns.Value);
}
else
{
_dictionaryWriter.WriteQualifiedName(name, ns);
}
}
internal void WriteStartElement(string localName, string ns)
{
WriteStartElement(null, localName, ns);
}
internal virtual void WriteStartElement(string prefix, string localName, string ns)
{
_writer.WriteStartElement(prefix, localName, ns);
_depth++;
_prefixes = 1;
}
public void WriteStartElement(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
{
WriteStartElement(null, localName, namespaceUri);
}
internal void WriteStartElement(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri)
{
if (_dictionaryWriter != null)
{
_dictionaryWriter.WriteStartElement(prefix, localName, namespaceUri);
}
else
{
_writer.WriteStartElement(prefix, (localName == null ? null : localName.Value), (namespaceUri == null ? null : namespaceUri.Value));
}
_depth++;
_prefixes = 1;
}
internal void WriteStartElementPrimitive(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
{
if (_dictionaryWriter != null)
{
_dictionaryWriter.WriteStartElement(null, localName, namespaceUri);
}
else
{
_writer.WriteStartElement(null, (localName == null ? null : localName.Value), (namespaceUri == null ? null : namespaceUri.Value));
}
}
internal void WriteEndElementPrimitive()
{
_writer.WriteEndElement();
}
internal WriteState WriteState => _writer.WriteState;
internal string XmlLang => _writer.XmlLang;
internal XmlSpace XmlSpace => _writer.XmlSpace;
public void WriteNamespaceDecl(XmlDictionaryString ns)
{
WriteXmlnsAttribute(ns);
}
private Exception CreateInvalidPrimitiveTypeException(Type type)
{
return new System.Runtime.Serialization.InvalidDataContractException(SR.Format(SR.InvalidPrimitiveType, DataContract.GetClrTypeFullName(type)));
}
internal void WriteAnyType(object value)
{
WriteAnyType(value, value.GetType());
}
internal void WriteAnyType(object value, Type valueType)
{
bool handled = true;
switch (Type.GetTypeCode(valueType))
{
case TypeCode.Boolean:
WriteBoolean((bool)value);
break;
case TypeCode.Char:
WriteChar((char)value);
break;
case TypeCode.Byte:
WriteUnsignedByte((byte)value);
break;
case TypeCode.Int16:
WriteShort((short)value);
break;
case TypeCode.Int32:
WriteInt((int)value);
break;
case TypeCode.Int64:
WriteLong((long)value);
break;
case TypeCode.Single:
WriteFloat((float)value);
break;
case TypeCode.Double:
WriteDouble((double)value);
break;
case TypeCode.Decimal:
WriteDecimal((decimal)value);
break;
case TypeCode.DateTime:
WriteDateTime((DateTime)value);
break;
case TypeCode.String:
WriteString((string)value);
break;
case TypeCode.SByte:
WriteSignedByte((sbyte)value);
break;
case TypeCode.UInt16:
WriteUnsignedShort((ushort)value);
break;
case TypeCode.UInt32:
WriteUnsignedInt((uint)value);
break;
case TypeCode.UInt64:
WriteUnsignedLong((ulong)value);
break;
case TypeCode.Empty:
case TypeCode.DBNull:
case TypeCode.Object:
default:
if (valueType == Globals.TypeOfByteArray)
{
WriteBase64((byte[])value);
}
else if (valueType == Globals.TypeOfObject)
{
//Write Nothing
}
else if (valueType == Globals.TypeOfTimeSpan)
{
WriteTimeSpan((TimeSpan)value);
}
else if (valueType == Globals.TypeOfGuid)
{
WriteGuid((Guid)value);
}
else if (valueType == Globals.TypeOfUri)
{
WriteUri((Uri)value);
}
else if (valueType == Globals.TypeOfXmlQualifiedName)
{
WriteQName((XmlQualifiedName)value);
}
else
{
handled = false;
}
break;
}
if (!handled)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidPrimitiveTypeException(valueType));
}
}
internal void WriteExtensionData(IDataNode dataNode)
{
bool handled = true;
Type valueType = dataNode.DataType;
switch (Type.GetTypeCode(valueType))
{
case TypeCode.Boolean:
WriteBoolean(((DataNode<bool>)dataNode).GetValue());
break;
case TypeCode.Char:
WriteChar(((DataNode<char>)dataNode).GetValue());
break;
case TypeCode.Byte:
WriteUnsignedByte(((DataNode<byte>)dataNode).GetValue());
break;
case TypeCode.Int16:
WriteShort(((DataNode<short>)dataNode).GetValue());
break;
case TypeCode.Int32:
WriteInt(((DataNode<int>)dataNode).GetValue());
break;
case TypeCode.Int64:
WriteLong(((DataNode<long>)dataNode).GetValue());
break;
case TypeCode.Single:
WriteFloat(((DataNode<float>)dataNode).GetValue());
break;
case TypeCode.Double:
WriteDouble(((DataNode<double>)dataNode).GetValue());
break;
case TypeCode.Decimal:
WriteDecimal(((DataNode<decimal>)dataNode).GetValue());
break;
case TypeCode.DateTime:
WriteDateTime(((DataNode<DateTime>)dataNode).GetValue());
break;
case TypeCode.String:
WriteString(((DataNode<string>)dataNode).GetValue());
break;
case TypeCode.SByte:
WriteSignedByte(((DataNode<sbyte>)dataNode).GetValue());
break;
case TypeCode.UInt16:
WriteUnsignedShort(((DataNode<ushort>)dataNode).GetValue());
break;
case TypeCode.UInt32:
WriteUnsignedInt(((DataNode<uint>)dataNode).GetValue());
break;
case TypeCode.UInt64:
WriteUnsignedLong(((DataNode<ulong>)dataNode).GetValue());
break;
case TypeCode.Empty:
case TypeCode.DBNull:
case TypeCode.Object:
default:
if (valueType == Globals.TypeOfByteArray)
{
WriteBase64(((DataNode<byte[]>)dataNode).GetValue());
}
else if (valueType == Globals.TypeOfObject)
{
object obj = dataNode.Value;
if (obj != null)
{
WriteAnyType(obj);
}
}
else if (valueType == Globals.TypeOfTimeSpan)
{
WriteTimeSpan(((DataNode<TimeSpan>)dataNode).GetValue());
}
else if (valueType == Globals.TypeOfGuid)
{
WriteGuid(((DataNode<Guid>)dataNode).GetValue());
}
else if (valueType == Globals.TypeOfUri)
{
WriteUri(((DataNode<Uri>)dataNode).GetValue());
}
else if (valueType == Globals.TypeOfXmlQualifiedName)
{
WriteQName(((DataNode<XmlQualifiedName>)dataNode).GetValue());
}
else
{
handled = false;
}
break;
}
if (!handled)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidPrimitiveTypeException(valueType));
}
}
internal void WriteString(string value)
{
_writer.WriteValue(value);
}
internal virtual void WriteBoolean(bool value)
{
_writer.WriteValue(value);
}
public void WriteBoolean(bool value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteBoolean(value);
WriteEndElementPrimitive();
}
internal virtual void WriteDateTime(DateTime value)
{
_writer.WriteValue(value);
}
public void WriteDateTime(DateTime value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteDateTime(value);
WriteEndElementPrimitive();
}
internal virtual void WriteDecimal(decimal value)
{
_writer.WriteValue(value);
}
public void WriteDecimal(decimal value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteDecimal(value);
WriteEndElementPrimitive();
}
internal virtual void WriteDouble(double value)
{
_writer.WriteValue(value);
}
public void WriteDouble(double value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteDouble(value);
WriteEndElementPrimitive();
}
internal virtual void WriteInt(int value)
{
_writer.WriteValue(value);
}
public void WriteInt(int value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteInt(value);
WriteEndElementPrimitive();
}
internal virtual void WriteLong(long value)
{
_writer.WriteValue(value);
}
public void WriteLong(long value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteLong(value);
WriteEndElementPrimitive();
}
internal virtual void WriteFloat(float value)
{
_writer.WriteValue(value);
}
public void WriteFloat(float value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteFloat(value);
WriteEndElementPrimitive();
}
private const int CharChunkSize = 76;
private const int ByteChunkSize = CharChunkSize / 4 * 3;
internal virtual void WriteBase64(byte[] bytes)
{
if (bytes == null)
{
return;
}
_writer.WriteBase64(bytes, 0, bytes.Length);
}
internal virtual void WriteShort(short value)
{
_writer.WriteValue(value);
}
public void WriteShort(short value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteShort(value);
WriteEndElementPrimitive();
}
internal virtual void WriteUnsignedByte(byte value)
{
_writer.WriteValue(value);
}
public void WriteUnsignedByte(byte value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteUnsignedByte(value);
WriteEndElementPrimitive();
}
internal virtual void WriteSignedByte(sbyte value)
{
_writer.WriteValue(value);
}
public void WriteSignedByte(sbyte value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteSignedByte(value);
WriteEndElementPrimitive();
}
internal virtual void WriteUnsignedInt(uint value)
{
_writer.WriteValue(value);
}
public void WriteUnsignedInt(uint value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteUnsignedInt(value);
WriteEndElementPrimitive();
}
internal virtual void WriteUnsignedLong(ulong value)
{
_writer.WriteRaw(XmlConvert.ToString(value));
}
public void WriteUnsignedLong(ulong value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteUnsignedLong(value);
WriteEndElementPrimitive();
}
internal virtual void WriteUnsignedShort(ushort value)
{
_writer.WriteValue(value);
}
public void WriteUnsignedShort(ushort value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteUnsignedShort(value);
WriteEndElementPrimitive();
}
internal virtual void WriteChar(char value)
{
_writer.WriteValue(value);
}
public void WriteChar(char value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteChar(value);
WriteEndElementPrimitive();
}
internal void WriteTimeSpan(TimeSpan value)
{
_writer.WriteRaw(XmlConvert.ToString(value));
}
public void WriteTimeSpan(TimeSpan value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteTimeSpan(value);
WriteEndElementPrimitive();
}
internal void WriteGuid(Guid value)
{
_writer.WriteRaw(value.ToString());
}
public void WriteGuid(Guid value, XmlDictionaryString name, XmlDictionaryString ns)
{
WriteStartElementPrimitive(name, ns);
WriteGuid(value);
WriteEndElementPrimitive();
}
internal void WriteUri(Uri value)
{
_writer.WriteString(value.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped));
}
internal virtual void WriteQName(XmlQualifiedName value)
{
if (value != XmlQualifiedName.Empty)
{
WriteXmlnsAttribute(value.Namespace);
WriteQualifiedName(value.Name, value.Namespace);
}
}
internal void WriteQualifiedName(string localName, string ns)
{
_writer.WriteQualifiedName(localName, ns);
}
internal void WriteQualifiedName(XmlDictionaryString localName, XmlDictionaryString ns)
{
if (_dictionaryWriter == null)
{
_writer.WriteQualifiedName(localName.Value, ns.Value);
}
else
{
_dictionaryWriter.WriteQualifiedName(localName, ns);
}
}
public void WriteBooleanArray(bool[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
{
if (_dictionaryWriter == null)
{
for (int i = 0; i < value.Length; i++)
{
WriteBoolean(value[i], itemName, itemNamespace);
}
}
else
{
_dictionaryWriter.WriteArray(null, itemName, itemNamespace, value, 0, value.Length);
}
}
public void WriteDateTimeArray(DateTime[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
{
if (_dictionaryWriter == null)
{
for (int i = 0; i < value.Length; i++)
{
WriteDateTime(value[i], itemName, itemNamespace);
}
}
else
{
_dictionaryWriter.WriteArray(null, itemName, itemNamespace, value, 0, value.Length);
}
}
public void WriteDecimalArray(decimal[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
{
if (_dictionaryWriter == null)
{
for (int i = 0; i < value.Length; i++)
{
WriteDecimal(value[i], itemName, itemNamespace);
}
}
else
{
_dictionaryWriter.WriteArray(null, itemName, itemNamespace, value, 0, value.Length);
}
}
public void WriteInt32Array(int[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
{
if (_dictionaryWriter == null)
{
for (int i = 0; i < value.Length; i++)
{
WriteInt(value[i], itemName, itemNamespace);
}
}
else
{
_dictionaryWriter.WriteArray(null, itemName, itemNamespace, value, 0, value.Length);
}
}
public void WriteInt64Array(long[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
{
if (_dictionaryWriter == null)
{
for (int i = 0; i < value.Length; i++)
{
WriteLong(value[i], itemName, itemNamespace);
}
}
else
{
_dictionaryWriter.WriteArray(null, itemName, itemNamespace, value, 0, value.Length);
}
}
public void WriteSingleArray(float[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
{
if (_dictionaryWriter == null)
{
for (int i = 0; i < value.Length; i++)
{
WriteFloat(value[i], itemName, itemNamespace);
}
}
else
{
_dictionaryWriter.WriteArray(null, itemName, itemNamespace, value, 0, value.Length);
}
}
public void WriteDoubleArray(double[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
{
if (_dictionaryWriter == null)
{
for (int i = 0; i < value.Length; i++)
{
WriteDouble(value[i], itemName, itemNamespace);
}
}
else
{
_dictionaryWriter.WriteArray(null, itemName, itemNamespace, value, 0, value.Length);
}
}
}
}

View File

@@ -0,0 +1,387 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;
using InvalidDataContractException = System.Runtime.Serialization.InvalidDataContractException;
namespace Compat.Runtime.Serialization
{
public class XsdDataContractExporter
{
private ExportOptions options;
private XmlSchemaSet schemas;
private DataContractSet dataContractSet;
public XsdDataContractExporter()
{
}
public XsdDataContractExporter(XmlSchemaSet schemas)
{
this.schemas = schemas;
}
public ExportOptions Options
{
get => options;
set => options = value;
}
public XmlSchemaSet Schemas
{
get
{
XmlSchemaSet schemaSet = GetSchemaSet();
SchemaImporter.CompileSchemaSet(schemaSet);
return schemaSet;
}
}
private XmlSchemaSet GetSchemaSet()
{
if (schemas == null)
{
schemas = new XmlSchemaSet
{
XmlResolver = null
};
}
return schemas;
}
private DataContractSet DataContractSet
{
get
{
if (dataContractSet == null)
{
dataContractSet = new DataContractSet((Options == null) ? null : Options.GetSurrogate());
}
return dataContractSet;
}
}
public void Export(ICollection<Assembly> assemblies)
{
if (assemblies == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("assemblies"));
}
DataContractSet oldValue = (dataContractSet == null) ? null : new DataContractSet(dataContractSet);
try
{
foreach (Assembly assembly in assemblies)
{
if (assembly == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.CannotExportNullAssembly, "assemblies")));
}
Type[] types = assembly.GetTypes();
for (int j = 0; j < types.Length; j++)
{
CheckAndAddType(types[j]);
}
}
Export();
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
dataContractSet = oldValue;
throw;
}
}
public void Export(ICollection<Type> types)
{
if (types == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(types)));
}
DataContractSet oldValue = (dataContractSet == null) ? null : new DataContractSet(dataContractSet);
try
{
foreach (Type type in types)
{
if (type == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.CannotExportNullType, nameof(types))));
}
AddType(type);
}
Export();
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
dataContractSet = oldValue;
throw;
}
}
public void Export(Type type)
{
if (type == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(type)));
}
DataContractSet oldValue = (dataContractSet == null) ? null : new DataContractSet(dataContractSet);
try
{
AddType(type);
Export();
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
dataContractSet = oldValue;
throw;
}
}
public XmlQualifiedName GetSchemaTypeName(Type type)
{
if (type == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(type)));
}
type = GetSurrogatedType(type);
DataContract dataContract = DataContract.GetDataContract(type);
DataContractSet.EnsureTypeNotGeneric(dataContract.UnderlyingType);
XmlDataContract xmlDataContract = dataContract as XmlDataContract;
if (xmlDataContract != null && xmlDataContract.IsAnonymous)
{
return XmlQualifiedName.Empty;
}
return dataContract.StableName;
}
public XmlSchemaType GetSchemaType(Type type)
{
if (type == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("type"));
}
type = GetSurrogatedType(type);
DataContract dataContract = DataContract.GetDataContract(type);
DataContractSet.EnsureTypeNotGeneric(dataContract.UnderlyingType);
XmlDataContract xmlDataContract = dataContract as XmlDataContract;
if (xmlDataContract != null && xmlDataContract.IsAnonymous)
{
return xmlDataContract.XsdType;
}
return null;
}
public XmlQualifiedName GetRootElementName(Type type)
{
if (type == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("type"));
}
type = GetSurrogatedType(type);
DataContract dataContract = DataContract.GetDataContract(type);
DataContractSet.EnsureTypeNotGeneric(dataContract.UnderlyingType);
if (dataContract.HasRoot)
{
return new XmlQualifiedName(dataContract.TopLevelElementName.Value, dataContract.TopLevelElementNamespace.Value);
}
else
{
return null;
}
}
private Type GetSurrogatedType(Type type)
{
IDataContractSurrogate dataContractSurrogate;
if (options != null && (dataContractSurrogate = Options.GetSurrogate()) != null)
{
type = DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, type);
}
return type;
}
private void CheckAndAddType(Type type)
{
type = GetSurrogatedType(type);
if (!type.ContainsGenericParameters && DataContract.IsTypeSerializable(type))
{
AddType(type);
}
}
private void AddType(Type type)
{
DataContractSet.Add(type);
}
private void Export()
{
AddKnownTypes();
SchemaExporter schemaExporter = new SchemaExporter(GetSchemaSet(), DataContractSet);
schemaExporter.Export();
}
private void AddKnownTypes()
{
if (Options != null)
{
Collection<Type> knownTypes = Options.KnownTypes;
if (knownTypes != null)
{
for (int i = 0; i < knownTypes.Count; i++)
{
Type type = knownTypes[i];
if (type == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.CannotExportNullKnownType));
}
AddType(type);
}
}
}
}
public bool CanExport(ICollection<Assembly> assemblies)
{
if (assemblies == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("assemblies"));
}
DataContractSet oldValue = (dataContractSet == null) ? null : new DataContractSet(dataContractSet);
try
{
foreach (Assembly assembly in assemblies)
{
if (assembly == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.CannotExportNullAssembly, nameof(assemblies))));
}
Type[] types = assembly.GetTypes();
for (int j = 0; j < types.Length; j++)
{
CheckAndAddType(types[j]);
}
}
AddKnownTypes();
return true;
}
catch (InvalidDataContractException)
{
dataContractSet = oldValue;
return false;
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
dataContractSet = oldValue;
throw;
}
}
public bool CanExport(ICollection<Type> types)
{
if (types == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(types)));
}
DataContractSet oldValue = (dataContractSet == null) ? null : new DataContractSet(dataContractSet);
try
{
foreach (Type type in types)
{
if (type == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.CannotExportNullType, nameof(types))));
}
AddType(type);
}
AddKnownTypes();
return true;
}
catch (InvalidDataContractException)
{
dataContractSet = oldValue;
return false;
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
dataContractSet = oldValue;
throw;
}
}
public bool CanExport(Type type)
{
if (type == null)
{
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(type)));
}
DataContractSet oldValue = (dataContractSet == null) ? null : new DataContractSet(dataContractSet);
try
{
AddType(type);
AddKnownTypes();
return true;
}
catch (InvalidDataContractException)
{
dataContractSet = oldValue;
return false;
}
catch (Exception ex)
{
if (Fx.IsFatal(ex))
{
throw;
}
dataContractSet = oldValue;
throw;
}
}
}
}

View File

@@ -0,0 +1,601 @@
using Compat.Runtime.Serialization;
using System;
using System.Globalization;
using System.Security;
using System.Text;
namespace Compat.Text
{
internal class Base64Encoding : Encoding
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.StyleCop.CSharp.SpacingRules", "SA1025:CodeMustNotContainMultipleWhitespaceInARow", Justification = "This alignment is optimal.")]
private static readonly byte[] char2val = new byte[128]
{
/* 0-15 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 16-31 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 32-47 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 62, 0xFF, 0xFF, 0xFF, 63,
/* 48-63 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xFF, 0xFF, 0xFF, 64, 0xFF, 0xFF,
/* 64-79 */ 0xFF, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 80-95 */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 96-111 */ 0xFF, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
/* 112-127 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
private static readonly string val2char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
private static readonly byte[] val2byte = new byte[]
{
(byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', (byte)'O', (byte)'P',
(byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f',
(byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', (byte)'v',
(byte)'w', (byte)'x', (byte)'y', (byte)'z', (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/'
};
public override int GetMaxByteCount(int charCount)
{
if (charCount < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charCount), SR.ValueMustBeNonNegative));
}
if ((charCount % 4) != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Length, charCount.ToString(NumberFormatInfo.CurrentInfo))));
}
return charCount / 4 * 3;
}
private bool IsValidLeadBytes(int v1, int v2, int v3, int v4)
{
// First two chars of a four char base64 sequence can't be ==, and must be valid
return ((v1 | v2) < 64) && ((v3 | v4) != 0xFF);
}
private bool IsValidTailBytes(int v3, int v4)
{
// If the third char is = then the fourth char must be =
return !(v3 == 64 && v4 != 64);
}
public override unsafe int GetByteCount(char[] chars, int index, int count)
{
if (chars == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(chars)));
}
if (index < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(index), SR.ValueMustBeNonNegative));
}
if (index > chars.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(index), SR.Format(SR.OffsetExceedsBufferSize, chars.Length)));
}
if (count < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(count), SR.ValueMustBeNonNegative));
}
if (count > chars.Length - index)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.SizeExceedsRemainingBufferSpace, chars.Length - index)));
}
if (count == 0)
{
return 0;
}
if ((count % 4) != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Length, count.ToString(NumberFormatInfo.CurrentInfo))));
}
fixed (byte* _char2val = char2val)
{
fixed (char* _chars = &chars[index])
{
int totalCount = 0;
char* pch = _chars;
char* pchMax = _chars + count;
while (pch < pchMax)
{
Fx.Assert(pch + 4 <= pchMax, "");
char pch0 = pch[0];
char pch1 = pch[1];
char pch2 = pch[2];
char pch3 = pch[3];
if ((pch0 | pch1 | pch2 | pch3) >= 128)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Sequence, new string(pch, 0, 4), index + (int)(pch - _chars))));
}
// xx765432 xx107654 xx321076 xx543210
// 76543210 76543210 76543210
int v1 = _char2val[pch0];
int v2 = _char2val[pch1];
int v3 = _char2val[pch2];
int v4 = _char2val[pch3];
if (!IsValidLeadBytes(v1, v2, v3, v4) || !IsValidTailBytes(v3, v4))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Sequence, new string(pch, 0, 4), index + (int)(pch - _chars))));
}
int byteCount = (v4 != 64 ? 3 : (v3 != 64 ? 2 : 1));
totalCount += byteCount;
pch += 4;
}
return totalCount;
}
}
}
public override unsafe int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
if (chars == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(chars)));
}
if (charIndex < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charIndex), SR.ValueMustBeNonNegative));
}
if (charIndex > chars.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charIndex), SR.Format(SR.OffsetExceedsBufferSize, chars.Length)));
}
if (charCount < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charCount), SR.ValueMustBeNonNegative));
}
if (charCount > chars.Length - charIndex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charCount), SR.Format(SR.SizeExceedsRemainingBufferSpace, chars.Length - charIndex)));
}
if (bytes == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bytes)));
}
if (byteIndex < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteIndex), SR.ValueMustBeNonNegative));
}
if (byteIndex > bytes.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteIndex), SR.Format(SR.OffsetExceedsBufferSize, bytes.Length)));
}
if (charCount == 0)
{
return 0;
}
if ((charCount % 4) != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Length, charCount.ToString(NumberFormatInfo.CurrentInfo))));
}
fixed (byte* _char2val = char2val)
{
fixed (char* _chars = &chars[charIndex])
{
fixed (byte* _bytes = &bytes[byteIndex])
{
char* pch = _chars;
char* pchMax = _chars + charCount;
byte* pb = _bytes;
byte* pbMax = _bytes + bytes.Length - byteIndex;
while (pch < pchMax)
{
Fx.Assert(pch + 4 <= pchMax, "");
char pch0 = pch[0];
char pch1 = pch[1];
char pch2 = pch[2];
char pch3 = pch[3];
if ((pch0 | pch1 | pch2 | pch3) >= 128)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Sequence, new string(pch, 0, 4), charIndex + (int)(pch - _chars))));
}
// xx765432 xx107654 xx321076 xx543210
// 76543210 76543210 76543210
int v1 = _char2val[pch0];
int v2 = _char2val[pch1];
int v3 = _char2val[pch2];
int v4 = _char2val[pch3];
if (!IsValidLeadBytes(v1, v2, v3, v4) || !IsValidTailBytes(v3, v4))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Sequence, new string(pch, 0, 4), charIndex + (int)(pch - _chars))));
}
int byteCount = (v4 != 64 ? 3 : (v3 != 64 ? 2 : 1));
if (pb + byteCount > pbMax)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.XmlArrayTooSmall, nameof(bytes)));
}
pb[0] = (byte)((v1 << 2) | ((v2 >> 4) & 0x03));
if (byteCount > 1)
{
pb[1] = (byte)((v2 << 4) | ((v3 >> 2) & 0x0F));
if (byteCount > 2)
{
pb[2] = (byte)((v3 << 6) | ((v4 >> 0) & 0x3F));
}
}
pb += byteCount;
pch += 4;
}
return (int)(pb - _bytes);
}
}
}
}
public virtual unsafe int GetBytes(byte[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
if (chars == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(chars)));
}
if (charIndex < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charIndex), SR.ValueMustBeNonNegative));
}
if (charIndex > chars.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charIndex), SR.Format(SR.OffsetExceedsBufferSize, chars.Length)));
}
if (charCount < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charCount), SR.ValueMustBeNonNegative));
}
if (charCount > chars.Length - charIndex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charCount), SR.Format(SR.SizeExceedsRemainingBufferSpace, chars.Length - charIndex)));
}
if (bytes == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bytes)));
}
if (byteIndex < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteIndex), SR.ValueMustBeNonNegative));
}
if (byteIndex > bytes.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteIndex), SR.Format(SR.OffsetExceedsBufferSize, bytes.Length)));
}
if (charCount == 0)
{
return 0;
}
if ((charCount % 4) != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Length, charCount.ToString(NumberFormatInfo.CurrentInfo))));
}
fixed (byte* _char2val = char2val)
{
fixed (byte* _chars = &chars[charIndex])
{
fixed (byte* _bytes = &bytes[byteIndex])
{
byte* pch = _chars;
byte* pchMax = _chars + charCount;
byte* pb = _bytes;
byte* pbMax = _bytes + bytes.Length - byteIndex;
while (pch < pchMax)
{
Fx.Assert(pch + 4 <= pchMax, "");
byte pch0 = pch[0];
byte pch1 = pch[1];
byte pch2 = pch[2];
byte pch3 = pch[3];
if ((pch0 | pch1 | pch2 | pch3) >= 128)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Sequence, new string((sbyte*)pch, 0, 4), charIndex + (int)(pch - _chars))));
}
// xx765432 xx107654 xx321076 xx543210
// 76543210 76543210 76543210
int v1 = _char2val[pch0];
int v2 = _char2val[pch1];
int v3 = _char2val[pch2];
int v4 = _char2val[pch3];
if (!IsValidLeadBytes(v1, v2, v3, v4) || !IsValidTailBytes(v3, v4))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format(SR.XmlInvalidBase64Sequence, new string((sbyte*)pch, 0, 4), charIndex + (int)(pch - _chars))));
}
int byteCount = (v4 != 64 ? 3 : (v3 != 64 ? 2 : 1));
if (pb + byteCount > pbMax)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.XmlArrayTooSmall, nameof(bytes)));
}
pb[0] = (byte)((v1 << 2) | ((v2 >> 4) & 0x03));
if (byteCount > 1)
{
pb[1] = (byte)((v2 << 4) | ((v3 >> 2) & 0x0F));
if (byteCount > 2)
{
pb[2] = (byte)((v3 << 6) | ((v4 >> 0) & 0x3F));
}
}
pb += byteCount;
pch += 4;
}
return (int)(pb - _bytes);
}
}
}
}
public override int GetMaxCharCount(int byteCount)
{
if (byteCount < 0 || byteCount > int.MaxValue / 4 * 3 - 2)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteCount), SR.Format(SR.ValueMustBeInRange, 0, int.MaxValue / 4 * 3 - 2)));
}
return ((byteCount + 2) / 3) * 4;
}
public override int GetCharCount(byte[] bytes, int index, int count)
{
return GetMaxCharCount(count);
}
public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
{
if (bytes == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bytes)));
}
if (byteIndex < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteIndex), SR.ValueMustBeNonNegative));
}
if (byteIndex > bytes.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteIndex), SR.Format(SR.OffsetExceedsBufferSize, bytes.Length)));
}
if (byteCount < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteCount), SR.ValueMustBeNonNegative));
}
if (byteCount > bytes.Length - byteIndex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteCount), SR.Format(SR.SizeExceedsRemainingBufferSpace, bytes.Length - byteIndex)));
}
int charCount = GetCharCount(bytes, byteIndex, byteCount);
if (chars == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(chars)));
}
if (charIndex < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charIndex), SR.ValueMustBeNonNegative));
}
if (charIndex > chars.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charIndex), SR.Format(SR.OffsetExceedsBufferSize, chars.Length)));
}
if (charCount < 0 || charCount > chars.Length - charIndex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.XmlArrayTooSmall, nameof(chars)));
}
// We've computed exactly how many chars there are and verified that
// there's enough space in the char buffer, so we can proceed without
// checking the charCount.
if (byteCount > 0)
{
fixed (char* _val2char = val2char)
{
fixed (byte* _bytes = &bytes[byteIndex])
{
fixed (char* _chars = &chars[charIndex])
{
byte* pb = _bytes;
byte* pbMax = pb + byteCount - 3;
char* pch = _chars;
// Convert chunks of 3 bytes to 4 chars
while (pb <= pbMax)
{
// 76543210 76543210 76543210
// xx765432 xx107654 xx321076 xx543210
// Inspect the code carefully before you change this
pch[0] = _val2char[(pb[0] >> 2)];
pch[1] = _val2char[((pb[0] & 0x03) << 4) | (pb[1] >> 4)];
pch[2] = _val2char[((pb[1] & 0x0F) << 2) | (pb[2] >> 6)];
pch[3] = _val2char[pb[2] & 0x3F];
pb += 3;
pch += 4;
}
// Handle 1 or 2 trailing bytes
if (pb - pbMax == 2)
{
// 1 trailing byte
// 76543210 xxxxxxxx xxxxxxxx
// xx765432 xx10xxxx xxxxxxxx xxxxxxxx
pch[0] = _val2char[(pb[0] >> 2)];
pch[1] = _val2char[((pb[0] & 0x03) << 4)];
pch[2] = '=';
pch[3] = '=';
}
else if (pb - pbMax == 1)
{
// 2 trailing bytes
// 76543210 76543210 xxxxxxxx
// xx765432 xx107654 xx3210xx xxxxxxxx
pch[0] = _val2char[(pb[0] >> 2)];
pch[1] = _val2char[((pb[0] & 0x03) << 4) | (pb[1] >> 4)];
pch[2] = _val2char[((pb[1] & 0x0F) << 2)];
pch[3] = '=';
}
else
{
// 0 trailing bytes
Fx.Assert(pb - pbMax == 3, "");
}
}
}
}
}
return charCount;
}
public unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, byte[] chars, int charIndex)
{
if (bytes == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bytes)));
}
if (byteIndex < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteIndex), SR.ValueMustBeNonNegative));
}
if (byteIndex > bytes.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteIndex), SR.Format(SR.OffsetExceedsBufferSize, bytes.Length)));
}
if (byteCount < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteCount), SR.ValueMustBeNonNegative));
}
if (byteCount > bytes.Length - byteIndex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(byteCount), SR.Format(SR.SizeExceedsRemainingBufferSpace, bytes.Length - byteIndex)));
}
int charCount = GetCharCount(bytes, byteIndex, byteCount);
if (chars == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(chars)));
}
if (charIndex < 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charIndex), SR.ValueMustBeNonNegative));
}
if (charIndex > chars.Length)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(charIndex), SR.Format(SR.OffsetExceedsBufferSize, chars.Length)));
}
if (charCount < 0 || charCount > chars.Length - charIndex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.XmlArrayTooSmall, nameof(chars)));
}
// We've computed exactly how many chars there are and verified that
// there's enough space in the char buffer, so we can proceed without
// checking the charCount.
if (byteCount > 0)
{
fixed (byte* _val2byte = val2byte)
{
fixed (byte* _bytes = &bytes[byteIndex])
{
fixed (byte* _chars = &chars[charIndex])
{
byte* pb = _bytes;
byte* pbMax = pb + byteCount - 3;
byte* pch = _chars;
// Convert chunks of 3 bytes to 4 chars
while (pb <= pbMax)
{
// 76543210 76543210 76543210
// xx765432 xx107654 xx321076 xx543210
// Inspect the code carefully before you change this
pch[0] = _val2byte[(pb[0] >> 2)];
pch[1] = _val2byte[((pb[0] & 0x03) << 4) | (pb[1] >> 4)];
pch[2] = _val2byte[((pb[1] & 0x0F) << 2) | (pb[2] >> 6)];
pch[3] = _val2byte[pb[2] & 0x3F];
pb += 3;
pch += 4;
}
// Handle 1 or 2 trailing bytes
if (pb - pbMax == 2)
{
// 1 trailing byte
// 76543210 xxxxxxxx xxxxxxxx
// xx765432 xx10xxxx xxxxxxxx xxxxxxxx
pch[0] = _val2byte[(pb[0] >> 2)];
pch[1] = _val2byte[((pb[0] & 0x03) << 4)];
pch[2] = (byte)'=';
pch[3] = (byte)'=';
}
else if (pb - pbMax == 1)
{
// 2 trailing bytes
// 76543210 76543210 xxxxxxxx
// xx765432 xx107654 xx3210xx xxxxxxxx
pch[0] = _val2byte[(pb[0] >> 2)];
pch[1] = _val2byte[((pb[0] & 0x03) << 4) | (pb[1] >> 4)];
pch[2] = _val2byte[((pb[1] & 0x0F) << 2)];
pch[3] = (byte)'=';
}
else
{
// 0 trailing bytes
Fx.Assert(pb - pbMax == 3, "");
}
}
}
}
}
return charCount;
}
}
}

View File

@@ -0,0 +1,422 @@
using System;
using System.Xml;
namespace Compat.Xml
{
internal abstract class ArrayHelper<TArgument, TArray>
{
private const int MaxInitialArrayLength = 65535;
public TArray[] ReadArray(XmlDictionaryReader reader, TArgument localName, TArgument namespaceUri, int maxArrayLength)
{
TArray[][] arrays = null;
TArray[] array = null;
int arrayCount = 0;
int totalRead = 0;
if (reader.TryGetArrayLength(out int count))
{
if (count > maxArrayLength)
{
XmlExceptionHelper.ThrowMaxArrayLengthOrMaxItemsQuotaExceeded(reader, maxArrayLength);
}
if (count > MaxInitialArrayLength)
{
count = MaxInitialArrayLength;
}
}
else
{
count = 32;
}
while (true)
{
array = new TArray[count];
int read = 0;
while (read < array.Length)
{
int actual = ReadArray(reader, localName, namespaceUri, array, read, array.Length - read);
if (actual == 0)
{
break;
}
read += actual;
}
if (totalRead > maxArrayLength - read)
{
XmlExceptionHelper.ThrowMaxArrayLengthOrMaxItemsQuotaExceeded(reader, maxArrayLength);
}
totalRead += read;
if (read < array.Length || reader.NodeType == XmlNodeType.EndElement)
{
break;
}
if (arrays == null)
{
arrays = new TArray[32][];
}
arrays[arrayCount++] = array;
count = count * 2;
}
if (totalRead != array.Length || arrayCount > 0)
{
TArray[] newArray = new TArray[totalRead];
int offset = 0;
for (int i = 0; i < arrayCount; i++)
{
Array.Copy(arrays[i], 0, newArray, offset, arrays[i].Length);
offset += arrays[i].Length;
}
Array.Copy(array, 0, newArray, offset, totalRead - offset);
array = newArray;
}
return array;
}
public void WriteArray(XmlDictionaryWriter writer, string prefix, TArgument localName, TArgument namespaceUri, XmlDictionaryReader reader)
{
if (reader.TryGetArrayLength(out int count))
{
count = Math.Min(count, 256);
}
else
{
count = 256;
}
TArray[] array = new TArray[count];
while (true)
{
int actual = ReadArray(reader, localName, namespaceUri, array, 0, array.Length);
if (actual == 0)
{
break;
}
WriteArray(writer, prefix, localName, namespaceUri, array, 0, actual);
}
}
protected abstract int ReadArray(XmlDictionaryReader reader, TArgument localName, TArgument namespaceUri, TArray[] array, int offset, int count);
protected abstract void WriteArray(XmlDictionaryWriter writer, string prefix, TArgument localName, TArgument namespaceUri, TArray[] array, int offset, int count);
}
// Supported array types
// bool
// Int16
// Int32
// Int64
// Float
// Double
// Decimal
// DateTime
// Guid
// TimeSpan
// Int8 is not supported since sbyte[] is non-cls compliant, and uncommon
// UniqueId is not supported since elements may be variable size strings
internal class BooleanArrayHelperWithString : ArrayHelper<string, bool>
{
public static readonly BooleanArrayHelperWithString Instance = new BooleanArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, bool[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, bool[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class BooleanArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, bool>
{
public static readonly BooleanArrayHelperWithDictionaryString Instance = new BooleanArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, bool[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, bool[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class Int16ArrayHelperWithString : ArrayHelper<string, short>
{
public static readonly Int16ArrayHelperWithString Instance = new Int16ArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, short[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, short[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class Int16ArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, short>
{
public static readonly Int16ArrayHelperWithDictionaryString Instance = new Int16ArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, short[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, short[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class Int32ArrayHelperWithString : ArrayHelper<string, int>
{
public static readonly Int32ArrayHelperWithString Instance = new Int32ArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, int[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, int[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class Int32ArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, int>
{
public static readonly Int32ArrayHelperWithDictionaryString Instance = new Int32ArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, int[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, int[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class Int64ArrayHelperWithString : ArrayHelper<string, long>
{
public static readonly Int64ArrayHelperWithString Instance = new Int64ArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, long[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, long[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class Int64ArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, long>
{
public static readonly Int64ArrayHelperWithDictionaryString Instance = new Int64ArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, long[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, long[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class SingleArrayHelperWithString : ArrayHelper<string, float>
{
public static readonly SingleArrayHelperWithString Instance = new SingleArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, float[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, float[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class SingleArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, float>
{
public static readonly SingleArrayHelperWithDictionaryString Instance = new SingleArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class DoubleArrayHelperWithString : ArrayHelper<string, double>
{
public static readonly DoubleArrayHelperWithString Instance = new DoubleArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, double[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, double[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class DoubleArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, double>
{
public static readonly DoubleArrayHelperWithDictionaryString Instance = new DoubleArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class DecimalArrayHelperWithString : ArrayHelper<string, decimal>
{
public static readonly DecimalArrayHelperWithString Instance = new DecimalArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, decimal[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, decimal[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class DecimalArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, decimal>
{
public static readonly DecimalArrayHelperWithDictionaryString Instance = new DecimalArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class DateTimeArrayHelperWithString : ArrayHelper<string, DateTime>
{
public static readonly DateTimeArrayHelperWithString Instance = new DateTimeArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, DateTime[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, DateTime[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class DateTimeArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, DateTime>
{
public static readonly DateTimeArrayHelperWithDictionaryString Instance = new DateTimeArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, DateTime[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, DateTime[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class GuidArrayHelperWithString : ArrayHelper<string, Guid>
{
public static readonly GuidArrayHelperWithString Instance = new GuidArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, Guid[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, Guid[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class GuidArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, Guid>
{
public static readonly GuidArrayHelperWithDictionaryString Instance = new GuidArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Guid[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Guid[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class TimeSpanArrayHelperWithString : ArrayHelper<string, TimeSpan>
{
public static readonly TimeSpanArrayHelperWithString Instance = new TimeSpanArrayHelperWithString();
protected override int ReadArray(XmlDictionaryReader reader, string localName, string namespaceUri, TimeSpan[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, string localName, string namespaceUri, TimeSpan[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
internal class TimeSpanArrayHelperWithDictionaryString : ArrayHelper<XmlDictionaryString, TimeSpan>
{
public static readonly TimeSpanArrayHelperWithDictionaryString Instance = new TimeSpanArrayHelperWithDictionaryString();
protected override int ReadArray(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString namespaceUri, TimeSpan[] array, int offset, int count)
{
return reader.ReadArray(localName, namespaceUri, array, offset, count);
}
protected override void WriteArray(XmlDictionaryWriter writer, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, TimeSpan[] array, int offset, int count)
{
writer.WriteArray(prefix, localName, namespaceUri, array, offset, count);
}
}
}

View File

@@ -0,0 +1,288 @@
////using System.ServiceModel.Channels;
using System;
using System.Globalization;
using System.Xml;
namespace Compat.Xml
{
internal static class XmlExceptionHelper
{
private static void ThrowXmlException(XmlDictionaryReader reader, string res)
{
ThrowXmlException(reader, res, null);
}
private static void ThrowXmlException(XmlDictionaryReader reader, string res, string arg1)
{
ThrowXmlException(reader, res, arg1, null);
}
private static void ThrowXmlException(XmlDictionaryReader reader, string res, string arg1, string arg2)
{
ThrowXmlException(reader, res, arg1, arg2, null);
}
private static void ThrowXmlException(XmlDictionaryReader reader, string res, string arg1, string arg2, string arg3)
{
string s = SR.Format(res, arg1, arg2, arg3);
if (reader is IXmlLineInfo lineInfo && lineInfo.HasLineInfo())
{
s += " " + SR.Format(SR.XmlLineInfo, lineInfo.LineNumber, lineInfo.LinePosition);
}
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.Xml.XmlException(s));
}
public static void ThrowXmlException(XmlDictionaryReader reader, XmlException exception)
{
string s = exception.Message;
if (reader is IXmlLineInfo lineInfo && lineInfo.HasLineInfo())
{
s += " " + SR.Format(SR.XmlLineInfo, lineInfo.LineNumber, lineInfo.LinePosition);
}
throw Compat.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(s));
}
private static string GetName(string prefix, string localName)
{
if (prefix.Length == 0)
{
return localName;
}
else
{
return string.Concat(prefix, ":", localName);
}
}
private static string GetWhatWasFound(XmlDictionaryReader reader)
{
if (reader.EOF)
{
return SR.XmlFoundEndOfFile;
}
switch (reader.NodeType)
{
case XmlNodeType.Element:
return SR.Format(SR.XmlFoundElement, GetName(reader.Prefix, reader.LocalName), reader.NamespaceURI);
case XmlNodeType.EndElement:
return SR.Format(SR.XmlFoundEndElement, GetName(reader.Prefix, reader.LocalName), reader.NamespaceURI);
case XmlNodeType.Text:
case XmlNodeType.Whitespace:
case XmlNodeType.SignificantWhitespace:
return SR.Format(SR.XmlFoundText, reader.Value);
case XmlNodeType.Comment:
return SR.Format(SR.XmlFoundComment, reader.Value);
case XmlNodeType.CDATA:
return SR.Format(SR.XmlFoundCData, reader.Value);
}
return SR.Format(SR.XmlFoundNodeType, reader.NodeType);
}
//public static void ThrowStartElementExpected(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlStartElementExpected, GetWhatWasFound(reader));
//}
//public static void ThrowStartElementExpected(XmlDictionaryReader reader, string name)
//{
// ThrowXmlException(reader, SR.XmlStartElementNameExpected, name, GetWhatWasFound(reader));
//}
//public static void ThrowStartElementExpected(XmlDictionaryReader reader, string localName, string ns)
//{
// ThrowXmlException(reader, SR.XmlStartElementLocalNameNsExpected, localName, ns, GetWhatWasFound(reader));
//}
//public static void ThrowStartElementExpected(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString ns)
//{
// ThrowStartElementExpected(reader, localName?.Value, ns?.Value);
//}
//public static void ThrowFullStartElementExpected(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlFullStartElementExpected, GetWhatWasFound(reader));
//}
//public static void ThrowFullStartElementExpected(XmlDictionaryReader reader, string name)
//{
// ThrowXmlException(reader, SR.XmlFullStartElementNameExpected, name, GetWhatWasFound(reader));
//}
//public static void ThrowFullStartElementExpected(XmlDictionaryReader reader, string localName, string ns)
//{
// ThrowXmlException(reader, SR.XmlFullStartElementLocalNameNsExpected, localName, ns, GetWhatWasFound(reader));
//}
//public static void ThrowFullStartElementExpected(XmlDictionaryReader reader, XmlDictionaryString localName, XmlDictionaryString ns)
//{
// ThrowFullStartElementExpected(reader, localName?.Value, ns?.Value);
//}
//public static void ThrowEndElementExpected(XmlDictionaryReader reader, string localName, string ns)
//{
// ThrowXmlException(reader, SR.XmlEndElementExpected, localName, ns, GetWhatWasFound(reader));
//}
//public static void ThrowMaxStringContentLengthExceeded(XmlDictionaryReader reader, int maxStringContentLength)
//{
// ThrowXmlException(reader, SR.XmlMaxStringContentLengthExceeded, maxStringContentLength.ToString(NumberFormatInfo.CurrentInfo));
//}
//public static void ThrowMaxArrayLengthExceeded(XmlDictionaryReader reader, int maxArrayLength)
//{
// ThrowXmlException(reader, SR.XmlMaxArrayLengthExceeded, maxArrayLength.ToString(NumberFormatInfo.CurrentInfo));
//}
public static void ThrowMaxArrayLengthOrMaxItemsQuotaExceeded(XmlDictionaryReader reader, int maxQuota)
{
ThrowXmlException(reader, SR.XmlMaxArrayLengthOrMaxItemsQuotaExceeded, maxQuota.ToString(NumberFormatInfo.CurrentInfo));
}
//public static void ThrowMaxDepthExceeded(XmlDictionaryReader reader, int maxDepth)
//{
// ThrowXmlException(reader, SR.XmlMaxDepthExceeded, maxDepth.ToString(NumberFormatInfo.CurrentInfo));
//}
//public static void ThrowMaxBytesPerReadExceeded(XmlDictionaryReader reader, int maxBytesPerRead)
//{
// ThrowXmlException(reader, SR.XmlMaxBytesPerReadExceeded, maxBytesPerRead.ToString(NumberFormatInfo.CurrentInfo));
//}
//public static void ThrowMaxNameTableCharCountExceeded(XmlDictionaryReader reader, int maxNameTableCharCount)
//{
// ThrowXmlException(reader, SR.XmlMaxNameTableCharCountExceeded, maxNameTableCharCount.ToString(NumberFormatInfo.CurrentInfo));
//}
//public static void ThrowBase64DataExpected(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlBase64DataExpected, GetWhatWasFound(reader));
//}
//public static void ThrowUndefinedPrefix(XmlDictionaryReader reader, string prefix)
//{
// ThrowXmlException(reader, SR.XmlUndefinedPrefix, prefix);
//}
//public static void ThrowProcessingInstructionNotSupported(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlProcessingInstructionNotSupported);
//}
//public static void ThrowInvalidXml(XmlDictionaryReader reader, byte b)
//{
// ThrowXmlException(reader, SR.XmlInvalidXmlByte, b.ToString("X2", CultureInfo.InvariantCulture));
//}
//public static void ThrowUnexpectedEndOfFile(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlUnexpectedEndOfFile, ((XmlBaseReader)reader).GetOpenElements());
//}
//public static void ThrowUnexpectedEndElement(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlUnexpectedEndElement);
//}
//public static void ThrowTokenExpected(XmlDictionaryReader reader, string expected, char found)
//{
// ThrowXmlException(reader, SR.XmlTokenExpected, expected, found.ToString());
//}
//public static void ThrowTokenExpected(XmlDictionaryReader reader, string expected, string found)
//{
// ThrowXmlException(reader, SR.XmlTokenExpected, expected, found);
//}
//public static void ThrowInvalidCharRef(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlInvalidCharRef);
//}
//public static void ThrowTagMismatch(XmlDictionaryReader reader, string expectedPrefix, string expectedLocalName, string foundPrefix, string foundLocalName)
//{
// ThrowXmlException(reader, SR.XmlTagMismatch, GetName(expectedPrefix, expectedLocalName), GetName(foundPrefix, foundLocalName));
//}
//public static void ThrowDuplicateXmlnsAttribute(XmlDictionaryReader reader, string localName, string ns)
//{
// string name;
// if (localName.Length == 0)
// {
// name = "xmlns";
// }
// else
// {
// name = "xmlns:" + localName;
// }
// ThrowXmlException(reader, SR.XmlDuplicateAttribute, name, name, ns);
//}
//public static void ThrowDuplicateAttribute(XmlDictionaryReader reader, string prefix1, string prefix2, string localName, string ns)
//{
// ThrowXmlException(reader, SR.XmlDuplicateAttribute, GetName(prefix1, localName), GetName(prefix2, localName), ns);
//}
//public static void ThrowInvalidBinaryFormat(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlInvalidFormat);
//}
//public static void ThrowInvalidRootData(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlInvalidRootData);
//}
//public static void ThrowMultipleRootElements(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlMultipleRootElements);
//}
//public static void ThrowDeclarationNotFirst(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlDeclNotFirst);
//}
//public static void ThrowConversionOverflow(XmlDictionaryReader reader, string value, string type)
//{
// ThrowXmlException(reader, SR.XmlConversionOverflow, value, type);
//}
//public static void ThrowXmlDictionaryStringIDOutOfRange(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlDictionaryStringIDRange, XmlDictionaryString.MinKey.ToString(NumberFormatInfo.CurrentInfo), XmlDictionaryString.MaxKey.ToString(NumberFormatInfo.CurrentInfo));
//}
//public static void ThrowXmlDictionaryStringIDUndefinedStatic(XmlDictionaryReader reader, int key)
//{
// ThrowXmlException(reader, SR.XmlDictionaryStringIDUndefinedStatic, key.ToString(NumberFormatInfo.CurrentInfo));
//}
//public static void ThrowXmlDictionaryStringIDUndefinedSession(XmlDictionaryReader reader, int key)
//{
// ThrowXmlException(reader, SR.XmlDictionaryStringIDUndefinedSession, key.ToString(NumberFormatInfo.CurrentInfo));
//}
//public static void ThrowEmptyNamespace(XmlDictionaryReader reader)
//{
// ThrowXmlException(reader, SR.XmlEmptyNamespaceRequiresNullPrefix);
//}
public static XmlException CreateConversionException(string value, string type, Exception exception)
{
return new XmlException(SR.Format(SR.XmlInvalidConversion, value, type), exception);
}
public static XmlException CreateEncodingException(byte[] buffer, int offset, int count, Exception exception)
{
return CreateEncodingException(new System.Text.UTF8Encoding(false, false).GetString(buffer, offset, count), exception);
}
public static XmlException CreateEncodingException(string value, Exception exception)
{
return new XmlException(SR.Format(SR.XmlInvalidUTF8Bytes, value), exception);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,136 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Resources;
using System.Runtime.CompilerServices;
namespace Compat
{
internal partial class SR
{
// This method is used to decide if we need to append the exception message parameters to the message when calling SR.Format.
// by default it returns false.
// Native code generators can replace the value this returns based on user input at the time of native code generation.
// Marked as NoInlining because if this is used in an AoT compiled app that is not compiled into a single file, the user
// could compile each module with a different setting for this. We want to make sure there's a consistent behavior
// that doesn't depend on which native module this method got inlined into.
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool UsingResourceKeys() => false;
internal static string GetResourceString(string resourceKey, string? defaultString = null)
{
if (UsingResourceKeys())
{
return defaultString ?? resourceKey;
}
string? resourceString = null;
try
{
resourceString = ResourceManager.GetString(resourceKey);
}
catch (MissingManifestResourceException) { }
if (defaultString != null && resourceKey.Equals(resourceString))
{
return defaultString;
}
return resourceString!; // only null if missing resources
}
internal static string Format(string resourceFormat, object? p1)
{
if (UsingResourceKeys())
{
return string.Join(", ", resourceFormat, p1);
}
return string.Format(resourceFormat, p1);
}
internal static string Format(string resourceFormat, object? p1, object? p2)
{
if (UsingResourceKeys())
{
return string.Join(", ", resourceFormat, p1, p2);
}
return string.Format(resourceFormat, p1, p2);
}
internal static string Format(string resourceFormat, object? p1, object? p2, object? p3)
{
if (UsingResourceKeys())
{
return string.Join(", ", resourceFormat, p1, p2, p3);
}
return string.Format(resourceFormat, p1, p2, p3);
}
internal static string Format(string resourceFormat, params object?[]? args)
{
if (args != null)
{
if (UsingResourceKeys())
{
return resourceFormat + ", " + string.Join(", ", args);
}
return string.Format(resourceFormat, args);
}
return resourceFormat;
}
internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1)
{
if (UsingResourceKeys())
{
return string.Join(", ", resourceFormat, p1);
}
return string.Format(provider, resourceFormat, p1);
}
internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2)
{
if (UsingResourceKeys())
{
return string.Join(", ", resourceFormat, p1, p2);
}
return string.Format(provider, resourceFormat, p1, p2);
}
internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3)
{
if (UsingResourceKeys())
{
return string.Join(", ", resourceFormat, p1, p2, p3);
}
return string.Format(provider, resourceFormat, p1, p2, p3);
}
internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args)
{
if (args != null)
{
if (UsingResourceKeys())
{
return resourceFormat + ", " + string.Join(", ", args);
}
return string.Format(provider, resourceFormat, args);
}
return resourceFormat;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,123 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29209.152
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Compat.Private.Serialization", "Compat.Private.Serialization\Compat.Private.Serialization.csproj", "{1F4EB25F-3A60-45DC-A547-47847B194B32}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AB2CF6F8-831A-440A-B90A-4C1EB3437A15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB2CF6F8-831A-440A-B90A-4C1EB3437A15}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB2CF6F8-831A-440A-B90A-4C1EB3437A15}.Debug|x86.ActiveCfg = Debug|Any CPU
{AB2CF6F8-831A-440A-B90A-4C1EB3437A15}.Debug|x86.Build.0 = Debug|Any CPU
{AB2CF6F8-831A-440A-B90A-4C1EB3437A15}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB2CF6F8-831A-440A-B90A-4C1EB3437A15}.Release|Any CPU.Build.0 = Release|Any CPU
{AB2CF6F8-831A-440A-B90A-4C1EB3437A15}.Release|x86.ActiveCfg = Release|Any CPU
{AB2CF6F8-831A-440A-B90A-4C1EB3437A15}.Release|x86.Build.0 = Release|Any CPU
{998759D0-5251-44FB-B5ED-331D28751F1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{998759D0-5251-44FB-B5ED-331D28751F1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{998759D0-5251-44FB-B5ED-331D28751F1C}.Debug|x86.ActiveCfg = Debug|Any CPU
{998759D0-5251-44FB-B5ED-331D28751F1C}.Debug|x86.Build.0 = Debug|Any CPU
{998759D0-5251-44FB-B5ED-331D28751F1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{998759D0-5251-44FB-B5ED-331D28751F1C}.Release|Any CPU.Build.0 = Release|Any CPU
{998759D0-5251-44FB-B5ED-331D28751F1C}.Release|x86.ActiveCfg = Release|Any CPU
{998759D0-5251-44FB-B5ED-331D28751F1C}.Release|x86.Build.0 = Release|Any CPU
{A2AEAA66-FA33-437C-BC21-E644A4865543}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2AEAA66-FA33-437C-BC21-E644A4865543}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2AEAA66-FA33-437C-BC21-E644A4865543}.Debug|x86.ActiveCfg = Debug|Any CPU
{A2AEAA66-FA33-437C-BC21-E644A4865543}.Debug|x86.Build.0 = Debug|Any CPU
{A2AEAA66-FA33-437C-BC21-E644A4865543}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2AEAA66-FA33-437C-BC21-E644A4865543}.Release|Any CPU.Build.0 = Release|Any CPU
{A2AEAA66-FA33-437C-BC21-E644A4865543}.Release|x86.ActiveCfg = Release|Any CPU
{A2AEAA66-FA33-437C-BC21-E644A4865543}.Release|x86.Build.0 = Release|Any CPU
{624AA825-698D-490D-8C71-1126035E96F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{624AA825-698D-490D-8C71-1126035E96F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{624AA825-698D-490D-8C71-1126035E96F2}.Debug|x86.ActiveCfg = Debug|Any CPU
{624AA825-698D-490D-8C71-1126035E96F2}.Debug|x86.Build.0 = Debug|Any CPU
{624AA825-698D-490D-8C71-1126035E96F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{624AA825-698D-490D-8C71-1126035E96F2}.Release|Any CPU.Build.0 = Release|Any CPU
{624AA825-698D-490D-8C71-1126035E96F2}.Release|x86.ActiveCfg = Release|Any CPU
{624AA825-698D-490D-8C71-1126035E96F2}.Release|x86.Build.0 = Release|Any CPU
{29E0781B-FEED-47A4-B5D0-F3F47C642DE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29E0781B-FEED-47A4-B5D0-F3F47C642DE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29E0781B-FEED-47A4-B5D0-F3F47C642DE3}.Debug|x86.ActiveCfg = Debug|Any CPU
{29E0781B-FEED-47A4-B5D0-F3F47C642DE3}.Debug|x86.Build.0 = Debug|Any CPU
{29E0781B-FEED-47A4-B5D0-F3F47C642DE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29E0781B-FEED-47A4-B5D0-F3F47C642DE3}.Release|Any CPU.Build.0 = Release|Any CPU
{29E0781B-FEED-47A4-B5D0-F3F47C642DE3}.Release|x86.ActiveCfg = Release|Any CPU
{29E0781B-FEED-47A4-B5D0-F3F47C642DE3}.Release|x86.Build.0 = Release|Any CPU
{4D9C3EA3-30AD-43C2-835E-166A42872C03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4D9C3EA3-30AD-43C2-835E-166A42872C03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4D9C3EA3-30AD-43C2-835E-166A42872C03}.Debug|x86.ActiveCfg = Debug|Any CPU
{4D9C3EA3-30AD-43C2-835E-166A42872C03}.Debug|x86.Build.0 = Debug|Any CPU
{4D9C3EA3-30AD-43C2-835E-166A42872C03}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4D9C3EA3-30AD-43C2-835E-166A42872C03}.Release|Any CPU.Build.0 = Release|Any CPU
{4D9C3EA3-30AD-43C2-835E-166A42872C03}.Release|x86.ActiveCfg = Release|Any CPU
{4D9C3EA3-30AD-43C2-835E-166A42872C03}.Release|x86.Build.0 = Release|Any CPU
{35BD700E-2888-4B11-ABFA-D49371E9ECDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{35BD700E-2888-4B11-ABFA-D49371E9ECDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{35BD700E-2888-4B11-ABFA-D49371E9ECDE}.Debug|x86.ActiveCfg = Debug|Any CPU
{35BD700E-2888-4B11-ABFA-D49371E9ECDE}.Debug|x86.Build.0 = Debug|Any CPU
{35BD700E-2888-4B11-ABFA-D49371E9ECDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{35BD700E-2888-4B11-ABFA-D49371E9ECDE}.Release|Any CPU.Build.0 = Release|Any CPU
{35BD700E-2888-4B11-ABFA-D49371E9ECDE}.Release|x86.ActiveCfg = Release|Any CPU
{35BD700E-2888-4B11-ABFA-D49371E9ECDE}.Release|x86.Build.0 = Release|Any CPU
{C1853B29-C445-4098-81A5-3ADB633DF213}.Debug|Any CPU.ActiveCfg = Debug|x86
{C1853B29-C445-4098-81A5-3ADB633DF213}.Debug|x86.ActiveCfg = Debug|x86
{C1853B29-C445-4098-81A5-3ADB633DF213}.Debug|x86.Build.0 = Debug|x86
{C1853B29-C445-4098-81A5-3ADB633DF213}.Release|Any CPU.ActiveCfg = Release|x86
{C1853B29-C445-4098-81A5-3ADB633DF213}.Release|x86.ActiveCfg = Release|x86
{C1853B29-C445-4098-81A5-3ADB633DF213}.Release|x86.Build.0 = Release|x86
{302B8E43-8366-4E01-B35F-CB0C97902806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{302B8E43-8366-4E01-B35F-CB0C97902806}.Debug|Any CPU.Build.0 = Debug|Any CPU
{302B8E43-8366-4E01-B35F-CB0C97902806}.Debug|x86.ActiveCfg = Debug|Any CPU
{302B8E43-8366-4E01-B35F-CB0C97902806}.Debug|x86.Build.0 = Debug|Any CPU
{302B8E43-8366-4E01-B35F-CB0C97902806}.Release|Any CPU.ActiveCfg = Release|Any CPU
{302B8E43-8366-4E01-B35F-CB0C97902806}.Release|Any CPU.Build.0 = Release|Any CPU
{302B8E43-8366-4E01-B35F-CB0C97902806}.Release|x86.ActiveCfg = Release|Any CPU
{302B8E43-8366-4E01-B35F-CB0C97902806}.Release|x86.Build.0 = Release|Any CPU
{DAFF1345-4EB5-449E-94CE-1064C9E98FA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DAFF1345-4EB5-449E-94CE-1064C9E98FA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DAFF1345-4EB5-449E-94CE-1064C9E98FA9}.Debug|x86.ActiveCfg = Debug|Any CPU
{DAFF1345-4EB5-449E-94CE-1064C9E98FA9}.Debug|x86.Build.0 = Debug|Any CPU
{DAFF1345-4EB5-449E-94CE-1064C9E98FA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DAFF1345-4EB5-449E-94CE-1064C9E98FA9}.Release|Any CPU.Build.0 = Release|Any CPU
{DAFF1345-4EB5-449E-94CE-1064C9E98FA9}.Release|x86.ActiveCfg = Release|Any CPU
{DAFF1345-4EB5-449E-94CE-1064C9E98FA9}.Release|x86.Build.0 = Release|Any CPU
{1F4EB25F-3A60-45DC-A547-47847B194B32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F4EB25F-3A60-45DC-A547-47847B194B32}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F4EB25F-3A60-45DC-A547-47847B194B32}.Debug|x86.ActiveCfg = Debug|Any CPU
{1F4EB25F-3A60-45DC-A547-47847B194B32}.Debug|x86.Build.0 = Debug|Any CPU
{1F4EB25F-3A60-45DC-A547-47847B194B32}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F4EB25F-3A60-45DC-A547-47847B194B32}.Release|Any CPU.Build.0 = Release|Any CPU
{1F4EB25F-3A60-45DC-A547-47847B194B32}.Release|x86.ActiveCfg = Release|Any CPU
{1F4EB25F-3A60-45DC-A547-47847B194B32}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{624AA825-698D-490D-8C71-1126035E96F2} = {A3A5753A-2E8F-4970-B7BB-AA59E3C49247}
{29E0781B-FEED-47A4-B5D0-F3F47C642DE3} = {76D59EF6-6073-4E0A-B2CC-A69FCF66557A}
{4D9C3EA3-30AD-43C2-835E-166A42872C03} = {6EC5CC4A-E47A-4945-B986-645EEE26E6DD}
{35BD700E-2888-4B11-ABFA-D49371E9ECDE} = {6EC5CC4A-E47A-4945-B986-645EEE26E6DD}
{C1853B29-C445-4098-81A5-3ADB633DF213} = {76D59EF6-6073-4E0A-B2CC-A69FCF66557A}
{302B8E43-8366-4E01-B35F-CB0C97902806} = {76D59EF6-6073-4E0A-B2CC-A69FCF66557A}
{0E9962A0-1883-4D05-A162-02BE32F9B6C4} = {76D59EF6-6073-4E0A-B2CC-A69FCF66557A}
{DAE39861-D2F3-419B-9E8A-E783F0C5E89E} = {0E9962A0-1883-4D05-A162-02BE32F9B6C4}
{6EC5CC4A-E47A-4945-B986-645EEE26E6DD} = {DAE39861-D2F3-419B-9E8A-E783F0C5E89E}
{AB081229-928D-4718-A905-E35062D720CB} = {0E9962A0-1883-4D05-A162-02BE32F9B6C4}
{5A0F307E-BCA1-4BD7-9A5B-CF77607CA079} = {AB081229-928D-4718-A905-E35062D720CB}
{DAFF1345-4EB5-449E-94CE-1064C9E98FA9} = {5A0F307E-BCA1-4BD7-9A5B-CF77607CA079}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FB69BC62-AC69-4BB8-AB33-DF7E370C9F5B}
EndGlobalSection
EndGlobal