Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / Data / System / Data / Common / ObjectStorage.cs / 1 / ObjectStorage.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //[....] //----------------------------------------------------------------------------- namespace System.Data.Common { using System; using System.Data; using System.Xml; using System.IO; using System.Xml.Serialization; using System.Collections; using System.Collections.Generic; using System.Diagnostics; internal sealed class ObjectStorage : DataStorage { static private readonly Object defaultValue = null; private enum Families { DATETIME, NUMBER, STRING, BOOLEAN, ARRAY }; private object[] values; private readonly bool implementsIXmlSerializable; internal ObjectStorage(DataColumn column, Type type) : base(column, type, defaultValue, DBNull.Value, typeof(ICloneable).IsAssignableFrom(type)) { implementsIXmlSerializable = typeof(IXmlSerializable).IsAssignableFrom(type); } override public Object Aggregate(int[] records, AggregateType kind) { throw ExceptionBuilder.AggregateException(kind, DataType); } override public int Compare(int recordNo1, int recordNo2) { object valueNo1 = values[recordNo1]; object valueNo2 = values[recordNo2]; if (valueNo1 == valueNo2) return 0; if (valueNo1 == null) return -1; if (valueNo2 == null) return 1; IComparable icomparable = (valueNo1 as IComparable); if (null != icomparable) { try { return icomparable.CompareTo(valueNo2); } catch(ArgumentException e) { ExceptionBuilder.TraceExceptionWithoutRethrow(e); } } return CompareWithFamilies(valueNo1, valueNo2); } override public int CompareValueTo(int recordNo1, Object value) { object valueNo1 = Get(recordNo1); if (valueNo1 is IComparable) { if (value.GetType() == valueNo1.GetType()) return((IComparable) valueNo1).CompareTo(value); } if (valueNo1 == value) return 0; if (valueNo1 == null) { if (NullValue == value) { return 0; } return -1; } if ((NullValue == value) || (null == value)) { return 1; } return CompareWithFamilies(valueNo1, value); } private int CompareTo(object valueNo1, object valueNo2) { if (valueNo1 == null) return -1; if (valueNo2 == null) return 1; if (valueNo1 == valueNo2) return 0; if (valueNo1 == NullValue) return -1; if (valueNo2 == NullValue) return 1; if (valueNo1 is IComparable) { try{ return ((IComparable) valueNo1).CompareTo(valueNo2); } catch(ArgumentException e) { ExceptionBuilder.TraceExceptionWithoutRethrow(e); } } return CompareWithFamilies(valueNo1, valueNo2); } private int CompareWithFamilies(Object valueNo1, Object valueNo2) { Families Family1 = GetFamily(valueNo1.GetType()); Families Family2 = GetFamily(valueNo2.GetType()); if (Family1 < Family2) return -1; else if (Family1 > Family2) return 1; else { switch (Family1) { case Families.BOOLEAN : valueNo1 = Convert.ToBoolean(valueNo1, FormatProvider); valueNo2 = Convert.ToBoolean(valueNo2, FormatProvider); break; case Families.DATETIME: valueNo1 = Convert.ToDateTime(valueNo1, FormatProvider); valueNo2 = Convert.ToDateTime(valueNo1, FormatProvider); break; case Families.NUMBER : valueNo1 = Convert.ToDouble(valueNo1, FormatProvider); valueNo2 = Convert.ToDouble(valueNo2, FormatProvider); break; case Families.ARRAY :{ Array arr1 = (Array) valueNo1; Array arr2 = (Array) valueNo2; if (arr1.Length > arr2.Length) return 1; else if (arr1.Length < arr2.Length) return -1; else { // same number of elements for (int i = 0; i < arr1.Length; i++){ int c = CompareTo(arr1.GetValue(i),arr2.GetValue(i)); if (c != 0) return c ; } } return 0; } default : valueNo1 = valueNo1.ToString(); valueNo2 = valueNo2.ToString(); break; } return ((IComparable) valueNo1).CompareTo(valueNo2); } } override public void Copy(int recordNo1, int recordNo2) { values[recordNo2] = values[recordNo1]; } override public Object Get(int recordNo) { Object value = values[recordNo]; if (null != value) { return value; } return NullValue; } private Families GetFamily(Type dataType) { switch (Type.GetTypeCode(dataType)) { case TypeCode.Boolean: return Families.BOOLEAN; case TypeCode.Char: return Families.STRING; case TypeCode.SByte: return Families.STRING; case TypeCode.Byte: return Families.STRING; case TypeCode.Int16: return Families.NUMBER; case TypeCode.UInt16: return Families.NUMBER; case TypeCode.Int32: return Families.NUMBER; case TypeCode.UInt32: return Families.NUMBER; case TypeCode.Int64: return Families.NUMBER; case TypeCode.UInt64: return Families.NUMBER; case TypeCode.Single: return Families.NUMBER; case TypeCode.Double: return Families.NUMBER; case TypeCode.Decimal: return Families.NUMBER; case TypeCode.DateTime: return Families.DATETIME; case TypeCode.String: return Families.STRING; default: if (typeof(TimeSpan) == dataType) { return Families.DATETIME; } else if(dataType.IsArray) { return Families.ARRAY; } else{ return Families.STRING; } } } override public bool IsNull(int record) { return (null == values[record]); } override public void Set(int recordNo, Object value) { System.Diagnostics.Debug.Assert(null != value, "null value"); if (NullValue == value) { values[recordNo] = null; } else if (DataType == typeof(Object) || DataType.IsInstanceOfType(value)) { values[recordNo] = value; } else { Type valType = value.GetType(); if (DataType == typeof(Guid) && valType == typeof(string)){ values[recordNo] = new Guid((string)value); } else if (DataType == typeof(byte[])) { if (valType == typeof(Boolean)){ values[recordNo] = BitConverter.GetBytes((Boolean)value); } else if (valType == typeof(Char)){ values[recordNo] = BitConverter.GetBytes((Char)value); } else if (valType == typeof(Int16)){ values[recordNo] = BitConverter.GetBytes((Int16)value); } else if (valType == typeof(Int32)){ values[recordNo] = BitConverter.GetBytes((Int32)value); } else if (valType == typeof(Int64)){ values[recordNo] = BitConverter.GetBytes((Int64)value); } else if (valType == typeof(UInt16)){ values[recordNo] = BitConverter.GetBytes((UInt16)value); } else if (valType == typeof(UInt32)){ values[recordNo] = BitConverter.GetBytes((UInt32)value); } else if (valType == typeof(UInt64)){ values[recordNo] = BitConverter.GetBytes((UInt64)value); } else if (valType == typeof(Single)){ values[recordNo] = BitConverter.GetBytes((Single)value); } else if (valType == typeof(Double)){ values[recordNo] = BitConverter.GetBytes((Double)value); } else { throw ExceptionBuilder.StorageSetFailed(); } } else { throw ExceptionBuilder.StorageSetFailed(); } } } override public void SetCapacity(int capacity) { object[] newValues = new object[capacity]; if (values != null) { Array.Copy(values, 0, newValues, 0, Math.Min(capacity, values.Length)); } values = newValues; } override public object ConvertXmlToObject(string s) { Type type = DataType; // real type of objects in this column if (type == typeof(byte[])) { return Convert.FromBase64String(s); } if (type == typeof(Type)){ return Type.GetType(s); } if (type == typeof (Guid)){ return (new Guid(s)); } if (type == typeof (Uri)){ return (new Uri(s)); } if (implementsIXmlSerializable) { object Obj = System.Activator.CreateInstance(DataType, true); StringReader strReader = new StringReader(s); using (XmlTextReader xmlTextReader = new XmlTextReader(strReader)) { ((IXmlSerializable)Obj).ReadXml(xmlTextReader); } return Obj; } StringReader strreader = new StringReader(s); XmlSerializer deserializerWithOutRootAttribute = ObjectStorage.GetXmlSerializer(type); return(deserializerWithOutRootAttribute.Deserialize(strreader)); } public override object ConvertXmlToObject(XmlReader xmlReader, XmlRootAttribute xmlAttrib) { object retValue = null; bool isBaseCLRType = false; bool legacyUDT = false; // in 1.0 and 1.1 we used to call ToString on CDT obj. so if we have the same case // we need to handle the case when we have column type as object. if (null == xmlAttrib) { // this means type implements IXmlSerializable Type type = null; string typeName = xmlReader.GetAttribute(Keywords.MSD_INSTANCETYPE, Keywords.MSDNS); if (typeName == null || typeName.Length == 0) { // No CDT polumorphism string xsdTypeName = xmlReader.GetAttribute(Keywords.TYPE, Keywords.XSINS); // this xsd type: Base type polymorphism if (null != xsdTypeName && xsdTypeName.Length > 0) { string [] _typename = xsdTypeName.Split(':'); if (_typename.Length == 2) { // split will return aray of size 1 if ":" is not there if (xmlReader.LookupNamespace(_typename[0]) == Keywords.XSDNS) { xsdTypeName = _typename[1]; // trim the prefix and just continue with } } // for other case, let say we have two ':' in type, the we throws (as old behavior) type = XSDSchema.XsdtoClr(xsdTypeName); isBaseCLRType = true; } else if (DataType == typeof(object)) {// there is no Keywords.MSD_INSTANCETYPE and no Keywords.TYPE legacyUDT = true; // see if our type is object } } if (legacyUDT) { // if Everett UDT, just read it and return string retValue = xmlReader.ReadString(); } else { if (typeName == Keywords.TYPEINSTANCE) { retValue = Type.GetType(xmlReader.ReadString()); xmlReader.Read(); // need to move to next node } else { if (null == type) { type = (typeName == null)? DataType : Type.GetType(typeName); } if (type == typeof(char) || type == typeof(Guid)) { //msdata:char and msdata:guid imply base types. isBaseCLRType=true; } if (type == typeof(object)) throw ExceptionBuilder.CanNotDeserializeObjectType(); if (!isBaseCLRType){ retValue = System.Activator.CreateInstance (type, true); Debug.Assert(xmlReader is DataTextReader, "Invalid DataTextReader is being passed to customer"); ((IXmlSerializable)retValue).ReadXml(xmlReader); } else { // Process Base CLR type // for Element Node, if it is Empty, ReadString does not move to End Element; we need to move it if(type == typeof(string) && xmlReader.NodeType == XmlNodeType.Element && xmlReader.IsEmptyElement) { retValue = string.Empty; } else { retValue = xmlReader.ReadString(); if (type != typeof(byte[])) { retValue = SqlConvert.ChangeTypeForXML(retValue, type); } else { retValue = Convert.FromBase64String(retValue.ToString()); } } xmlReader.Read(); } } } } else{ XmlSerializer deserializerWithRootAttribute = ObjectStorage.GetXmlSerializer(DataType, xmlAttrib); retValue = deserializerWithRootAttribute.Deserialize(xmlReader); } return retValue; } override public string ConvertObjectToXml(object value) { if ((value == null) || (value == NullValue))// this case wont happen, this is added in case if code in xml saver changes return String.Empty; Type type = DataType; if (type == typeof(byte[]) || (type == typeof(object) && (value is byte[]))) { return Convert.ToBase64String((byte[])value); } if ((type == typeof(Type)) || ((type == typeof(Object)) && (value is Type))) { return ((Type)value).AssemblyQualifiedName; } if (!IsTypeCustomType(value.GetType())){ // Guid and Type had TypeCode.Object return (string)SqlConvert.ChangeTypeForXML(value, typeof(string)); } if (Type.GetTypeCode(value.GetType()) != TypeCode.Object) { return value.ToString(); } StringWriter strwriter = new StringWriter(FormatProvider); if (implementsIXmlSerializable) { using (XmlTextWriter xmlTextWriter = new XmlTextWriter (strwriter)) { ((IXmlSerializable)value).WriteXml(xmlTextWriter); } return (strwriter.ToString()); } XmlSerializer serializerWithOutRootAttribute = ObjectStorage.GetXmlSerializer(value.GetType()); serializerWithOutRootAttribute.Serialize( strwriter, value); return strwriter.ToString(); } public override void ConvertObjectToXml(object value, XmlWriter xmlWriter, XmlRootAttribute xmlAttrib) { if (null == xmlAttrib) { // implements IXmlSerializable Debug.Assert(xmlWriter is DataTextWriter, "Invalid DataTextWriter is being passed to customer"); ((IXmlSerializable)value).WriteXml(xmlWriter); } else { XmlSerializer serializerWithRootAttribute = ObjectStorage.GetXmlSerializer(value.GetType(), xmlAttrib); serializerWithRootAttribute.Serialize(xmlWriter, value); } } override protected object GetEmptyStorage(int recordCount) { return new Object[recordCount]; } override protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex) { Object[] typedStore = (Object[]) store; typedStore[storeIndex] = values[record]; bool isNull = IsNull(record); nullbits.Set(storeIndex, isNull); if (!isNull && (typedStore[storeIndex] is DateTime)) { DateTime dt = (DateTime)typedStore[storeIndex]; if (dt.Kind == DateTimeKind.Local) { typedStore[storeIndex] = DateTime.SpecifyKind(dt.ToUniversalTime(), DateTimeKind.Local); } } } override protected void SetStorage(object store, BitArray nullbits) { values = (Object[]) store; for(int i = 0; i < values.Length; i++) { if (values[i] is DateTime) { DateTime dt = (DateTime) values[i]; if (dt.Kind == DateTimeKind.Local) { values[i] = (DateTime.SpecifyKind(dt, DateTimeKind.Utc)).ToLocalTime(); } } } // SetNullStorage(nullbits); -> No need to set bits, } // SQLBU 431443: dynamically generated assemblies not cached for XmlSerialization when serializable Udt does not implement IXmlSerializable, "memeory leak" private static readonly object _tempAssemblyCacheLock = new object(); private static Dictionary, XmlSerializer> _tempAssemblyCache; private static readonly XmlSerializerFactory _serializerFactory = new XmlSerializerFactory(); internal static XmlSerializer GetXmlSerializer(Type type) { // use factory which caches XmlSerializer as necessary XmlSerializer serializer = _serializerFactory.CreateSerializer(type); return serializer; } internal static XmlSerializer GetXmlSerializer(Type type, XmlRootAttribute attribute) { XmlSerializer serializer = null; KeyValuePair key = new KeyValuePair (type,attribute); Dictionary , XmlSerializer> cache = _tempAssemblyCache; if ((null == cache) || !cache.TryGetValue(key, out serializer)) { // not in cache, try again with lock because it may need to grow lock(_tempAssemblyCacheLock) { cache = _tempAssemblyCache; if ((null == cache) || !cache.TryGetValue(key, out serializer)) { // if still not in cache, make cache larger and add new XmlSerializer if (null != cache) { // create larger cache, because dictionary is not reader/writer safe // copy cache so that all readers don't take lock - only potential new writers // same logic used by DbConnectionFactory Dictionary , XmlSerializer> tmp = new Dictionary , XmlSerializer>( 1+cache.Count, TempAssemblyComparer.Default); foreach (KeyValuePair , XmlSerializer> entry in cache) { // copy contents from old cache to new cache tmp.Add(entry.Key, entry.Value); } cache = tmp; } else { // initial creation of cache cache = new Dictionary , XmlSerializer>( TempAssemblyComparer.Default); } // attribute is modifiable - but usuage from XmlSaver & XmlDataLoader & XmlDiffLoader // the instances are not modified, but to be safe - copy the XmlRootAttribute before caching key = new KeyValuePair (type, new XmlRootAttribute()); key.Value.ElementName = attribute.ElementName; key.Value.Namespace = attribute.Namespace; key.Value.DataType = attribute.DataType; key.Value.IsNullable = attribute.IsNullable; serializer = _serializerFactory.CreateSerializer(type, attribute); cache.Add(key, serializer); _tempAssemblyCache = cache; } } } return serializer; } private class TempAssemblyComparer : IEqualityComparer > { internal static readonly IEqualityComparer > Default = new TempAssemblyComparer(); private TempAssemblyComparer() { } public bool Equals(KeyValuePair x, KeyValuePair y) { return ((x.Key == y.Key) && // same type (((x.Value == null) && (y.Value == null)) || // XmlRootAttribute both null ((x.Value != null) && (y.Value != null) && // XmlRootAttribute both with value (x.Value.ElementName == y.Value.ElementName) && // all attribute elements are equal (x.Value.Namespace == y.Value.Namespace) && (x.Value.DataType == y.Value.DataType) && (x.Value.IsNullable == y.Value.IsNullable)))); } public int GetHashCode(KeyValuePair obj) { return unchecked(obj.Key.GetHashCode() + obj.Value.ElementName.GetHashCode()); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //[....] //----------------------------------------------------------------------------- namespace System.Data.Common { using System; using System.Data; using System.Xml; using System.IO; using System.Xml.Serialization; using System.Collections; using System.Collections.Generic; using System.Diagnostics; internal sealed class ObjectStorage : DataStorage { static private readonly Object defaultValue = null; private enum Families { DATETIME, NUMBER, STRING, BOOLEAN, ARRAY }; private object[] values; private readonly bool implementsIXmlSerializable; internal ObjectStorage(DataColumn column, Type type) : base(column, type, defaultValue, DBNull.Value, typeof(ICloneable).IsAssignableFrom(type)) { implementsIXmlSerializable = typeof(IXmlSerializable).IsAssignableFrom(type); } override public Object Aggregate(int[] records, AggregateType kind) { throw ExceptionBuilder.AggregateException(kind, DataType); } override public int Compare(int recordNo1, int recordNo2) { object valueNo1 = values[recordNo1]; object valueNo2 = values[recordNo2]; if (valueNo1 == valueNo2) return 0; if (valueNo1 == null) return -1; if (valueNo2 == null) return 1; IComparable icomparable = (valueNo1 as IComparable); if (null != icomparable) { try { return icomparable.CompareTo(valueNo2); } catch(ArgumentException e) { ExceptionBuilder.TraceExceptionWithoutRethrow(e); } } return CompareWithFamilies(valueNo1, valueNo2); } override public int CompareValueTo(int recordNo1, Object value) { object valueNo1 = Get(recordNo1); if (valueNo1 is IComparable) { if (value.GetType() == valueNo1.GetType()) return((IComparable) valueNo1).CompareTo(value); } if (valueNo1 == value) return 0; if (valueNo1 == null) { if (NullValue == value) { return 0; } return -1; } if ((NullValue == value) || (null == value)) { return 1; } return CompareWithFamilies(valueNo1, value); } private int CompareTo(object valueNo1, object valueNo2) { if (valueNo1 == null) return -1; if (valueNo2 == null) return 1; if (valueNo1 == valueNo2) return 0; if (valueNo1 == NullValue) return -1; if (valueNo2 == NullValue) return 1; if (valueNo1 is IComparable) { try{ return ((IComparable) valueNo1).CompareTo(valueNo2); } catch(ArgumentException e) { ExceptionBuilder.TraceExceptionWithoutRethrow(e); } } return CompareWithFamilies(valueNo1, valueNo2); } private int CompareWithFamilies(Object valueNo1, Object valueNo2) { Families Family1 = GetFamily(valueNo1.GetType()); Families Family2 = GetFamily(valueNo2.GetType()); if (Family1 < Family2) return -1; else if (Family1 > Family2) return 1; else { switch (Family1) { case Families.BOOLEAN : valueNo1 = Convert.ToBoolean(valueNo1, FormatProvider); valueNo2 = Convert.ToBoolean(valueNo2, FormatProvider); break; case Families.DATETIME: valueNo1 = Convert.ToDateTime(valueNo1, FormatProvider); valueNo2 = Convert.ToDateTime(valueNo1, FormatProvider); break; case Families.NUMBER : valueNo1 = Convert.ToDouble(valueNo1, FormatProvider); valueNo2 = Convert.ToDouble(valueNo2, FormatProvider); break; case Families.ARRAY :{ Array arr1 = (Array) valueNo1; Array arr2 = (Array) valueNo2; if (arr1.Length > arr2.Length) return 1; else if (arr1.Length < arr2.Length) return -1; else { // same number of elements for (int i = 0; i < arr1.Length; i++){ int c = CompareTo(arr1.GetValue(i),arr2.GetValue(i)); if (c != 0) return c ; } } return 0; } default : valueNo1 = valueNo1.ToString(); valueNo2 = valueNo2.ToString(); break; } return ((IComparable) valueNo1).CompareTo(valueNo2); } } override public void Copy(int recordNo1, int recordNo2) { values[recordNo2] = values[recordNo1]; } override public Object Get(int recordNo) { Object value = values[recordNo]; if (null != value) { return value; } return NullValue; } private Families GetFamily(Type dataType) { switch (Type.GetTypeCode(dataType)) { case TypeCode.Boolean: return Families.BOOLEAN; case TypeCode.Char: return Families.STRING; case TypeCode.SByte: return Families.STRING; case TypeCode.Byte: return Families.STRING; case TypeCode.Int16: return Families.NUMBER; case TypeCode.UInt16: return Families.NUMBER; case TypeCode.Int32: return Families.NUMBER; case TypeCode.UInt32: return Families.NUMBER; case TypeCode.Int64: return Families.NUMBER; case TypeCode.UInt64: return Families.NUMBER; case TypeCode.Single: return Families.NUMBER; case TypeCode.Double: return Families.NUMBER; case TypeCode.Decimal: return Families.NUMBER; case TypeCode.DateTime: return Families.DATETIME; case TypeCode.String: return Families.STRING; default: if (typeof(TimeSpan) == dataType) { return Families.DATETIME; } else if(dataType.IsArray) { return Families.ARRAY; } else{ return Families.STRING; } } } override public bool IsNull(int record) { return (null == values[record]); } override public void Set(int recordNo, Object value) { System.Diagnostics.Debug.Assert(null != value, "null value"); if (NullValue == value) { values[recordNo] = null; } else if (DataType == typeof(Object) || DataType.IsInstanceOfType(value)) { values[recordNo] = value; } else { Type valType = value.GetType(); if (DataType == typeof(Guid) && valType == typeof(string)){ values[recordNo] = new Guid((string)value); } else if (DataType == typeof(byte[])) { if (valType == typeof(Boolean)){ values[recordNo] = BitConverter.GetBytes((Boolean)value); } else if (valType == typeof(Char)){ values[recordNo] = BitConverter.GetBytes((Char)value); } else if (valType == typeof(Int16)){ values[recordNo] = BitConverter.GetBytes((Int16)value); } else if (valType == typeof(Int32)){ values[recordNo] = BitConverter.GetBytes((Int32)value); } else if (valType == typeof(Int64)){ values[recordNo] = BitConverter.GetBytes((Int64)value); } else if (valType == typeof(UInt16)){ values[recordNo] = BitConverter.GetBytes((UInt16)value); } else if (valType == typeof(UInt32)){ values[recordNo] = BitConverter.GetBytes((UInt32)value); } else if (valType == typeof(UInt64)){ values[recordNo] = BitConverter.GetBytes((UInt64)value); } else if (valType == typeof(Single)){ values[recordNo] = BitConverter.GetBytes((Single)value); } else if (valType == typeof(Double)){ values[recordNo] = BitConverter.GetBytes((Double)value); } else { throw ExceptionBuilder.StorageSetFailed(); } } else { throw ExceptionBuilder.StorageSetFailed(); } } } override public void SetCapacity(int capacity) { object[] newValues = new object[capacity]; if (values != null) { Array.Copy(values, 0, newValues, 0, Math.Min(capacity, values.Length)); } values = newValues; } override public object ConvertXmlToObject(string s) { Type type = DataType; // real type of objects in this column if (type == typeof(byte[])) { return Convert.FromBase64String(s); } if (type == typeof(Type)){ return Type.GetType(s); } if (type == typeof (Guid)){ return (new Guid(s)); } if (type == typeof (Uri)){ return (new Uri(s)); } if (implementsIXmlSerializable) { object Obj = System.Activator.CreateInstance(DataType, true); StringReader strReader = new StringReader(s); using (XmlTextReader xmlTextReader = new XmlTextReader(strReader)) { ((IXmlSerializable)Obj).ReadXml(xmlTextReader); } return Obj; } StringReader strreader = new StringReader(s); XmlSerializer deserializerWithOutRootAttribute = ObjectStorage.GetXmlSerializer(type); return(deserializerWithOutRootAttribute.Deserialize(strreader)); } public override object ConvertXmlToObject(XmlReader xmlReader, XmlRootAttribute xmlAttrib) { object retValue = null; bool isBaseCLRType = false; bool legacyUDT = false; // in 1.0 and 1.1 we used to call ToString on CDT obj. so if we have the same case // we need to handle the case when we have column type as object. if (null == xmlAttrib) { // this means type implements IXmlSerializable Type type = null; string typeName = xmlReader.GetAttribute(Keywords.MSD_INSTANCETYPE, Keywords.MSDNS); if (typeName == null || typeName.Length == 0) { // No CDT polumorphism string xsdTypeName = xmlReader.GetAttribute(Keywords.TYPE, Keywords.XSINS); // this xsd type: Base type polymorphism if (null != xsdTypeName && xsdTypeName.Length > 0) { string [] _typename = xsdTypeName.Split(':'); if (_typename.Length == 2) { // split will return aray of size 1 if ":" is not there if (xmlReader.LookupNamespace(_typename[0]) == Keywords.XSDNS) { xsdTypeName = _typename[1]; // trim the prefix and just continue with } } // for other case, let say we have two ':' in type, the we throws (as old behavior) type = XSDSchema.XsdtoClr(xsdTypeName); isBaseCLRType = true; } else if (DataType == typeof(object)) {// there is no Keywords.MSD_INSTANCETYPE and no Keywords.TYPE legacyUDT = true; // see if our type is object } } if (legacyUDT) { // if Everett UDT, just read it and return string retValue = xmlReader.ReadString(); } else { if (typeName == Keywords.TYPEINSTANCE) { retValue = Type.GetType(xmlReader.ReadString()); xmlReader.Read(); // need to move to next node } else { if (null == type) { type = (typeName == null)? DataType : Type.GetType(typeName); } if (type == typeof(char) || type == typeof(Guid)) { //msdata:char and msdata:guid imply base types. isBaseCLRType=true; } if (type == typeof(object)) throw ExceptionBuilder.CanNotDeserializeObjectType(); if (!isBaseCLRType){ retValue = System.Activator.CreateInstance (type, true); Debug.Assert(xmlReader is DataTextReader, "Invalid DataTextReader is being passed to customer"); ((IXmlSerializable)retValue).ReadXml(xmlReader); } else { // Process Base CLR type // for Element Node, if it is Empty, ReadString does not move to End Element; we need to move it if(type == typeof(string) && xmlReader.NodeType == XmlNodeType.Element && xmlReader.IsEmptyElement) { retValue = string.Empty; } else { retValue = xmlReader.ReadString(); if (type != typeof(byte[])) { retValue = SqlConvert.ChangeTypeForXML(retValue, type); } else { retValue = Convert.FromBase64String(retValue.ToString()); } } xmlReader.Read(); } } } } else{ XmlSerializer deserializerWithRootAttribute = ObjectStorage.GetXmlSerializer(DataType, xmlAttrib); retValue = deserializerWithRootAttribute.Deserialize(xmlReader); } return retValue; } override public string ConvertObjectToXml(object value) { if ((value == null) || (value == NullValue))// this case wont happen, this is added in case if code in xml saver changes return String.Empty; Type type = DataType; if (type == typeof(byte[]) || (type == typeof(object) && (value is byte[]))) { return Convert.ToBase64String((byte[])value); } if ((type == typeof(Type)) || ((type == typeof(Object)) && (value is Type))) { return ((Type)value).AssemblyQualifiedName; } if (!IsTypeCustomType(value.GetType())){ // Guid and Type had TypeCode.Object return (string)SqlConvert.ChangeTypeForXML(value, typeof(string)); } if (Type.GetTypeCode(value.GetType()) != TypeCode.Object) { return value.ToString(); } StringWriter strwriter = new StringWriter(FormatProvider); if (implementsIXmlSerializable) { using (XmlTextWriter xmlTextWriter = new XmlTextWriter (strwriter)) { ((IXmlSerializable)value).WriteXml(xmlTextWriter); } return (strwriter.ToString()); } XmlSerializer serializerWithOutRootAttribute = ObjectStorage.GetXmlSerializer(value.GetType()); serializerWithOutRootAttribute.Serialize( strwriter, value); return strwriter.ToString(); } public override void ConvertObjectToXml(object value, XmlWriter xmlWriter, XmlRootAttribute xmlAttrib) { if (null == xmlAttrib) { // implements IXmlSerializable Debug.Assert(xmlWriter is DataTextWriter, "Invalid DataTextWriter is being passed to customer"); ((IXmlSerializable)value).WriteXml(xmlWriter); } else { XmlSerializer serializerWithRootAttribute = ObjectStorage.GetXmlSerializer(value.GetType(), xmlAttrib); serializerWithRootAttribute.Serialize(xmlWriter, value); } } override protected object GetEmptyStorage(int recordCount) { return new Object[recordCount]; } override protected void CopyValue(int record, object store, BitArray nullbits, int storeIndex) { Object[] typedStore = (Object[]) store; typedStore[storeIndex] = values[record]; bool isNull = IsNull(record); nullbits.Set(storeIndex, isNull); if (!isNull && (typedStore[storeIndex] is DateTime)) { DateTime dt = (DateTime)typedStore[storeIndex]; if (dt.Kind == DateTimeKind.Local) { typedStore[storeIndex] = DateTime.SpecifyKind(dt.ToUniversalTime(), DateTimeKind.Local); } } } override protected void SetStorage(object store, BitArray nullbits) { values = (Object[]) store; for(int i = 0; i < values.Length; i++) { if (values[i] is DateTime) { DateTime dt = (DateTime) values[i]; if (dt.Kind == DateTimeKind.Local) { values[i] = (DateTime.SpecifyKind(dt, DateTimeKind.Utc)).ToLocalTime(); } } } // SetNullStorage(nullbits); -> No need to set bits, } // SQLBU 431443: dynamically generated assemblies not cached for XmlSerialization when serializable Udt does not implement IXmlSerializable, "memeory leak" private static readonly object _tempAssemblyCacheLock = new object(); private static Dictionary, XmlSerializer> _tempAssemblyCache; private static readonly XmlSerializerFactory _serializerFactory = new XmlSerializerFactory(); internal static XmlSerializer GetXmlSerializer(Type type) { // use factory which caches XmlSerializer as necessary XmlSerializer serializer = _serializerFactory.CreateSerializer(type); return serializer; } internal static XmlSerializer GetXmlSerializer(Type type, XmlRootAttribute attribute) { XmlSerializer serializer = null; KeyValuePair key = new KeyValuePair (type,attribute); Dictionary , XmlSerializer> cache = _tempAssemblyCache; if ((null == cache) || !cache.TryGetValue(key, out serializer)) { // not in cache, try again with lock because it may need to grow lock(_tempAssemblyCacheLock) { cache = _tempAssemblyCache; if ((null == cache) || !cache.TryGetValue(key, out serializer)) { // if still not in cache, make cache larger and add new XmlSerializer if (null != cache) { // create larger cache, because dictionary is not reader/writer safe // copy cache so that all readers don't take lock - only potential new writers // same logic used by DbConnectionFactory Dictionary , XmlSerializer> tmp = new Dictionary , XmlSerializer>( 1+cache.Count, TempAssemblyComparer.Default); foreach (KeyValuePair , XmlSerializer> entry in cache) { // copy contents from old cache to new cache tmp.Add(entry.Key, entry.Value); } cache = tmp; } else { // initial creation of cache cache = new Dictionary , XmlSerializer>( TempAssemblyComparer.Default); } // attribute is modifiable - but usuage from XmlSaver & XmlDataLoader & XmlDiffLoader // the instances are not modified, but to be safe - copy the XmlRootAttribute before caching key = new KeyValuePair (type, new XmlRootAttribute()); key.Value.ElementName = attribute.ElementName; key.Value.Namespace = attribute.Namespace; key.Value.DataType = attribute.DataType; key.Value.IsNullable = attribute.IsNullable; serializer = _serializerFactory.CreateSerializer(type, attribute); cache.Add(key, serializer); _tempAssemblyCache = cache; } } } return serializer; } private class TempAssemblyComparer : IEqualityComparer > { internal static readonly IEqualityComparer > Default = new TempAssemblyComparer(); private TempAssemblyComparer() { } public bool Equals(KeyValuePair x, KeyValuePair y) { return ((x.Key == y.Key) && // same type (((x.Value == null) && (y.Value == null)) || // XmlRootAttribute both null ((x.Value != null) && (y.Value != null) && // XmlRootAttribute both with value (x.Value.ElementName == y.Value.ElementName) && // all attribute elements are equal (x.Value.Namespace == y.Value.Namespace) && (x.Value.DataType == y.Value.DataType) && (x.Value.IsNullable == y.Value.IsNullable)))); } public int GetHashCode(KeyValuePair obj) { return unchecked(obj.Key.GetHashCode() + obj.Value.ElementName.GetHashCode()); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ScrollData.cs
- MaterialGroup.cs
- BindingMAnagerBase.cs
- RequestNavigateEventArgs.cs
- XmlSerializerSection.cs
- AnimationTimeline.cs
- ToggleButtonAutomationPeer.cs
- unitconverter.cs
- LabelDesigner.cs
- CodeIndexerExpression.cs
- ListCollectionView.cs
- ToolStripArrowRenderEventArgs.cs
- PeerCollaboration.cs
- StaticSiteMapProvider.cs
- SqlErrorCollection.cs
- PolyLineSegment.cs
- TextBoxRenderer.cs
- StaticResourceExtension.cs
- RootDesignerSerializerAttribute.cs
- SQLBoolean.cs
- TrackingServices.cs
- BooleanSwitch.cs
- HtmlEmptyTagControlBuilder.cs
- COM2IPerPropertyBrowsingHandler.cs
- TaskFormBase.cs
- XmlLanguage.cs
- TableDesigner.cs
- SafeWaitHandle.cs
- Base64Stream.cs
- OperationParameterInfoCollection.cs
- PageSettings.cs
- HttpDictionary.cs
- BehaviorDragDropEventArgs.cs
- QueryTaskGroupState.cs
- SessionParameter.cs
- Logging.cs
- WindowsSlider.cs
- Compress.cs
- TCEAdapterGenerator.cs
- Operand.cs
- PointIndependentAnimationStorage.cs
- SafeIUnknown.cs
- uribuilder.cs
- TextParentUndoUnit.cs
- WebSysDefaultValueAttribute.cs
- EditorZoneBase.cs
- SamlSubject.cs
- TextTabProperties.cs
- ScrollItemPattern.cs
- WebSysDefaultValueAttribute.cs
- LocalizabilityAttribute.cs
- ParseNumbers.cs
- XmlObjectSerializerReadContextComplexJson.cs
- SchemaNotation.cs
- MarkupCompilePass2.cs
- BCryptNative.cs
- StorageMappingItemCollection.cs
- PointKeyFrameCollection.cs
- AutomationAttributeInfo.cs
- ConfigurationManager.cs
- LoadGrammarCompletedEventArgs.cs
- Accessible.cs
- Tracking.cs
- SQLInt64Storage.cs
- ParagraphVisual.cs
- SerializationStore.cs
- messageonlyhwndwrapper.cs
- SimpleRecyclingCache.cs
- CodeAccessPermission.cs
- FamilyTypefaceCollection.cs
- exports.cs
- EventLogInformation.cs
- XmlSchemaValidator.cs
- NameValueFileSectionHandler.cs
- CheckBoxRenderer.cs
- SQLGuid.cs
- Image.cs
- PersonalizationStateQuery.cs
- Pkcs9Attribute.cs
- SerialReceived.cs
- Span.cs
- RankException.cs
- TextRangeSerialization.cs
- iisPickupDirectory.cs
- Adorner.cs
- PropertyInfoSet.cs
- IIS7WorkerRequest.cs
- OperationCanceledException.cs
- MetadataUtil.cs
- MediaContextNotificationWindow.cs
- TypedServiceChannelBuilder.cs
- BitSet.cs
- QuadraticBezierSegment.cs
- FontCacheUtil.cs
- AutomationAttributeInfo.cs
- FormatStringEditor.cs
- ValidationPropertyAttribute.cs
- TcpTransportSecurity.cs
- OdbcConnection.cs
- ProcessStartInfo.cs