ResXDataNode.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / WinForms / Managed / System / Resources / ResXDataNode.cs / 1 / ResXDataNode.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

#if SYSTEM_WEB  // See DevDiv 9030 
namespace System.PrivateResources { 
#else
namespace System.Resources { 
#endif

    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary; 
    using System; 
    using System.Windows.Forms;
    using System.Reflection; 
    using Microsoft.Win32;
    using System.Drawing;
    using System.IO;
    using System.Text; 
    using System.ComponentModel;
    using System.Collections; 
    using System.Runtime.CompilerServices; 
    using System.Resources;
    using System.Xml; 
    using System.ComponentModel.Design;
    using System.Globalization;
    using System.Security.Permissions;
#if SYSTEM_WEB 
    using System.Web;   // This is needed to access the SR resource strings
#endif 
 

    ///  
    /// 
    ///
    /// 
    [Serializable] 
    [PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
#if SYSTEM_WEB 
    internal sealed class ResXDataNode : ISerializable { 
#else
    public sealed class ResXDataNode : ISerializable { 
#endif

        private static readonly char[] SpecialChars = new char[]{' ', '\r', '\n'};
 
        private DataNodeInfo        nodeInfo;
 
        private string name; 
        private string comment;
#if UNUSED 
        private string mimeType;
        private string valueData;
#endif
 
        private string typeName; // is only used when we create a resxdatanode manually with an object and contains the FQN
 
        private string fileRefFullPath; 
        private string fileRefType;
        private string fileRefTextEncoding; 

        private object              value;
        private ResXFileRef         fileRef;
 
        private IFormatter binaryFormatter = null;
 
        // this is going to be used to check if a ResXDataNode is of type ResXFileRef 
        private static ITypeResolutionService internalTypeResolver = new AssemblyNamesTypeResolutionService(new AssemblyName[] { new AssemblyName("System.Windows.Forms") });
 

        // constructors

        private ResXDataNode() { 
        }
 
        //  
        // this is a deep clone
        // 
        internal ResXDataNode DeepClone() {
            ResXDataNode result = new ResXDataNode();
            result.nodeInfo = (this.nodeInfo != null) ? this.nodeInfo.Clone() : null; // nodeinfo is just made up of immutable objects, we don't need to clone it
            result.name = this.name; 
            result.comment = this.comment;
#if UNUSED 
            result.mimeType = this.mimeType; 
            result.valueData = this.valueData;
#endif 
            result.typeName = this.typeName;
            result.fileRefFullPath = this.fileRefFullPath;
            result.fileRefType = this.fileRefType;
            result.fileRefTextEncoding = this.fileRefTextEncoding; 
            result.value = this.value; // we don't clone the value, because we don't know how
            result.fileRef = (this.fileRef != null) ? this.fileRef.Clone() : null; 
            return result; 
        }
 
        /// 
        /// 
        ///
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
        [ 
            SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "name" is the name of the param passed in. 
                                                                                                        // So we don't have to localize it.
        ] 
        public ResXDataNode(string name, object value) {
            if(name == null) {
                throw (new ArgumentNullException("name"));
            } 
            if(name.Length == 0) {
                throw (new ArgumentException("name")); 
            } 

            Type valueType = (value == null) ? typeof(object) : value.GetType(); 
            if (value != null && !valueType.IsSerializable) {
                throw new InvalidOperationException(SR.GetString(SR.NotSerializableType, name, valueType.FullName));
            } else if (value!= null) {
                this.typeName = valueType.AssemblyQualifiedName; 
            }
 
            this.name = name; 
            this.value = value;
        } 

        /// 
        /// 
        /// 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] 
        [ 
            SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "name" is the name of the param passed in.
                                                                                                        // So we don't have to localize it. 
        ]
        public ResXDataNode(string name, ResXFileRef fileRef) {
            if(name == null) {
                throw (new ArgumentNullException("name")); 
            }
            if(fileRef == null) { 
                throw (new ArgumentNullException("fileRef")); 
            }
            if(name.Length == 0) { 
                throw (new ArgumentException("name"));
            }
            this.name = name;
            this.fileRef = fileRef; 
        }
 
        internal ResXDataNode(DataNodeInfo nodeInfo, string basePath) { 
            this.nodeInfo = nodeInfo;
            InitializeDataNode(basePath); 
        }

        private void InitializeDataNode(string basePath) {
 
            // we can only use our internal type resolver here
            // because we only want to check if this is a ResXFileRef node 
            // and we can't be sure that we have a typeResolutionService that can 
            // recognize this. It's not very clean but this should work.
            Type nodeType = null; 
            if(!string.IsNullOrEmpty(nodeInfo.TypeName)) // can be null if we have a string (default for string is TypeName == null)
                nodeType = internalTypeResolver.GetType(nodeInfo.TypeName, false, true);
            if(nodeType != null && nodeType.Equals(typeof(ResXFileRef))) {
                // we have a fileref, split the value data and populate the fields 
                string[] fileRefDetails = ResXFileRef.Converter.ParseResxFileRefString(nodeInfo.ValueData);
                if(fileRefDetails != null && fileRefDetails.Length > 1) { 
                    if(!Path.IsPathRooted(fileRefDetails[0]) && basePath != null) { 
                        fileRefFullPath = Path.Combine(basePath, fileRefDetails[0]);
                    } else { 
                        fileRefFullPath = fileRefDetails[0];
                    }
                    fileRefType = fileRefDetails[1];
                    if(fileRefDetails.Length > 2) { 
                        fileRefTextEncoding = fileRefDetails[2];
                    } 
                } 
            }
        } 


        /// 
        ///  
        ///
        ///  
        public string Comment { 
            get {
                string result = comment; 
                if(result == null && nodeInfo != null) {
                    result = nodeInfo.Comment;
                }
                return (result == null ? "" : result); 
            }
            set { 
                comment= value; 
            }
        } 

        /// 
        /// 
        /// 
        /// 
        public string Name { 
            get { 
                string result = name;
                if(result == null && nodeInfo != null) { 
                    result = nodeInfo.Name;
                }
                return result;
            } 
            [
                SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "Name" is the name of the property. 
                                                                                                            // So we don't have to localize it. 
            ]
            set { 
                if(value == null) {
                    throw (new ArgumentNullException("Name"));
                }
                if(value.Length == 0) { 
                    throw (new ArgumentException("Name"));
                } 
                name = value; 
            }
        } 

#if UNUSED
        private string MimeType {
            get { 
                string result = mimeType;
                if(result == null && nodeInfo != null) { 
                    result = nodeInfo.MimeType; 
                }
                return result; 
            }
        }

        private string ValueData { 
            get {
                string result = valueData; 
                if(result == null && nodeInfo != null) { 
                    result = nodeInfo.ValueData;
                } 
                return result;
            }
        }
#endif 

        ///  
        ///  
        ///
        ///  
        public ResXFileRef FileRef {
            get {
                if(FileRefFullPath==null) {
                    return null; 
                }
                if(fileRef == null) { 
                    if(String.IsNullOrEmpty(fileRefTextEncoding)) 
                    {
                        fileRef = new ResXFileRef(FileRefFullPath, FileRefType); 
                    } else {
                        fileRef = new ResXFileRef(FileRefFullPath, FileRefType, Encoding.GetEncoding(FileRefTextEncoding));
                    }
                } 
                return fileRef;
            } 
        } 

 
        private string FileRefFullPath {
            get {
                string result = (fileRef==null ? null : fileRef.FileName);
                if(result == null) { 
                    result = fileRefFullPath;
                } 
                return result; 
            }
        } 

        private string FileRefType {
            get {
                string result = (fileRef==null ? null : fileRef.TypeName); 
                if(result == null) {
                    result = fileRefType; 
                } 
                return result;
            } 
        }

        private string FileRefTextEncoding {
            get { 
                string result = (fileRef==null ? null : (fileRef.TextFileEncoding == null ? null : fileRef.TextFileEncoding.BodyName));
                if(result == null) { 
                    result = fileRefTextEncoding; 
                }
 
                return result;
            }
        }
 

#if !SYSTEM_WEB     // System.Web does not link with the Soap assembly 
        ///  
        ///     As a performance optimization, we isolate the soap class here in a separate
        ///     function.  We don't care about the binary formatter because it lives in 
        ///     mscorlib, which is already loaded.  The soap formatter lives in a separate
        ///     assembly, however, so there is value in preventing it from needlessly
        ///     being loaded.
        ///  
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        private IFormatter CreateSoapFormatter() { 
            return new System.Runtime.Serialization.Formatters.Soap.SoapFormatter(); 
        }
#endif 


        private static string ToBase64WrappedString(byte[] data) {
            const int lineWrap = 80; 
            const string crlf = "\r\n";
            const string prefix = "        "; 
            string raw = Convert.ToBase64String(data); 
            if (raw.Length > lineWrap) {
                StringBuilder output = new StringBuilder(raw.Length + (raw.Length / lineWrap) * 3); // word wrap on lineWrap chars, \r\n 
                int current = 0;
                for (; current < raw.Length - lineWrap; current+=lineWrap) {
                    output.Append(crlf);
                    output.Append(prefix); 
                    output.Append(raw, current, lineWrap);
                } 
                output.Append(crlf); 
                output.Append(prefix);
                output.Append(raw, current, raw.Length - current); 
                output.Append(crlf);
                return output.ToString();
            }
            else { 
                return raw;
            } 
        } 

        private void FillDataNodeInfoFromObject(DataNodeInfo nodeInfo, object value) { 
            if (value is string) {
                nodeInfo.ValueData = (string)value;
                if(value == null) {
                    nodeInfo.TypeName = typeof(ResXNullRef).AssemblyQualifiedName; 
                }
            } 
            else if (value is byte[]) { 
                nodeInfo.ValueData = ToBase64WrappedString((byte[])value);
                nodeInfo.TypeName = typeof(byte[]).AssemblyQualifiedName; 
            }
            else {
                Type valueType = (value == null) ? typeof(object) : value.GetType();
                if (value != null && !valueType.IsSerializable) { 
                    throw new InvalidOperationException(SR.GetString(SR.NotSerializableType, name, valueType.FullName));
                } 
                TypeConverter tc = TypeDescriptor.GetConverter(valueType); 
                bool toString = tc.CanConvertTo(typeof(string));
                bool fromString = tc.CanConvertFrom(typeof(string)); 
                try {
                    if (toString && fromString) {
                        nodeInfo.ValueData = tc.ConvertToInvariantString(value);
                        nodeInfo.TypeName = valueType.AssemblyQualifiedName; 
                        return;
                    } 
                } 
                catch (Exception ex) {
                    // Some custom type converters will throw in ConvertTo(string) 
                    // to indicate that this object should be serialized through ISeriazable
                    // instead of as a string. This is semi-wrong, but something we will have to
                    // live with to allow user created Cursors to be serializable.
                    if (ClientUtils.IsSecurityOrCriticalException(ex)) { 
                        throw;
                    } 
                } 
                catch {
                } 

                bool toByteArray = tc.CanConvertTo(typeof(byte[]));
                bool fromByteArray = tc.CanConvertFrom(typeof(byte[]));
                if (toByteArray && fromByteArray) { 
                    byte[] data = (byte[])tc.ConvertTo(value, typeof(byte[]));
                    string text = ToBase64WrappedString(data); 
                    nodeInfo.ValueData = text; 
                    nodeInfo.MimeType = ResXResourceWriter.ByteArraySerializedObjectMimeType;
                    nodeInfo.TypeName = valueType.AssemblyQualifiedName; 
                    return;
                }

                if (value == null) { 
                    nodeInfo.ValueData = string.Empty;
                    nodeInfo.TypeName = typeof(ResXNullRef).AssemblyQualifiedName; 
                } 
                else {
                    if (binaryFormatter == null) { 
                        binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                    }

                    MemoryStream ms = new MemoryStream(); 
                    if (binaryFormatter == null) {
                        binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
                    } 
                    IFormatter formatter = binaryFormatter;
                    formatter.Serialize(ms, value); 
                    string text = ToBase64WrappedString(ms.ToArray());
                    nodeInfo.ValueData = text;
                    nodeInfo.MimeType = ResXResourceWriter.DefaultSerializedObjectMimeType;
                } 
            }
 
        } 

 
        private object GenerateObjectFromDataNodeInfo(DataNodeInfo dataNodeInfo, ITypeResolutionService typeResolver) {
            object result = null;
            string mimeTypeName = dataNodeInfo.MimeType;
            // default behavior: if we dont have a type name, it's a string 
            string typeName = (dataNodeInfo.TypeName == null || dataNodeInfo.TypeName.Length==0 ? typeof(string).AssemblyQualifiedName : dataNodeInfo.TypeName);
 
            if (mimeTypeName != null && mimeTypeName.Length > 0) { 
                if (String.Equals(mimeTypeName, ResXResourceWriter.BinSerializedObjectMimeType)
                    || String.Equals(mimeTypeName, ResXResourceWriter.Beta2CompatSerializedObjectMimeType) 
                    || String.Equals(mimeTypeName, ResXResourceWriter.CompatBinSerializedObjectMimeType)) {
                    string text = dataNodeInfo.ValueData;
                    byte[] serializedData;
                    serializedData = FromBase64WrappedString(text); 

                    if (binaryFormatter == null) { 
                        binaryFormatter = new BinaryFormatter(); 
                        binaryFormatter.Binder = new ResXSerializationBinder(typeResolver);
                    } 
                    IFormatter formatter = binaryFormatter;
                    if (serializedData != null && serializedData.Length > 0) {
                        result = formatter.Deserialize(new MemoryStream(serializedData));
                        if (result is ResXNullRef) { 
                            result = null;
                        } 
                    } 
                }
#if !SYSTEM_WEB // System.Web does not link with the Soap assembly 
                else if (String.Equals(mimeTypeName, ResXResourceWriter.SoapSerializedObjectMimeType)
                         || String.Equals(mimeTypeName, ResXResourceWriter.CompatSoapSerializedObjectMimeType)) {
                    string text = dataNodeInfo.ValueData;
                    byte[] serializedData; 
                    serializedData = FromBase64WrappedString(text);
 
                    if (serializedData != null && serializedData.Length > 0) { 

                        // Performance : don't inline a new SoapFormatter here.  That will always bring in 
                        //               the soap assembly, which we don't want.  Throw this in another
                        //               function so the class doesn't have to get loaded.
                        //
                        IFormatter formatter = CreateSoapFormatter(); 
                        result = formatter.Deserialize(new MemoryStream(serializedData));
                        if (result is ResXNullRef) { 
                            result = null; 
                        }
                    } 
                }
#endif
                else if (String.Equals(mimeTypeName, ResXResourceWriter.ByteArraySerializedObjectMimeType)) {
                    if (typeName != null && typeName.Length > 0) { 
                        Type type = ResolveType(typeName, typeResolver);
                        if (type != null) { 
                            TypeConverter tc = TypeDescriptor.GetConverter(type); 
                            if (tc.CanConvertFrom(typeof(byte[]))) {
                                string text = dataNodeInfo.ValueData; 
                                byte[] serializedData;
                                serializedData = FromBase64WrappedString(text);

                                if (serializedData != null) { 
                                    result = tc.ConvertFrom(serializedData);
                                } 
                            } 
                        }
                        else { 
                            string newMessage = SR.GetString(SR.TypeLoadException, typeName, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X);
                            XmlException xml = new XmlException(newMessage, null, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X);
                            TypeLoadException newTle = new TypeLoadException(newMessage, xml);
 
                            throw newTle;
                        } 
                    } 
                }
            } 
            else if (typeName != null && typeName.Length > 0) {
                Type type = ResolveType(typeName, typeResolver);
                if (type != null) {
                    if (type == typeof(ResXNullRef)) { 
                        result = null;
                    } 
                    else if (typeName.IndexOf("System.Byte[]") != -1 && typeName.IndexOf("mscorlib") != -1) { 
                        // Handle byte[]'s, which are stored as base-64 encoded strings.
                        // We can't hard-code byte[] type name due to version number 
                        // updates & potential whitespace issues with ResX files.
                        result = FromBase64WrappedString(dataNodeInfo.ValueData);
                    }
                    else { 
                        TypeConverter tc = TypeDescriptor.GetConverter(type);
                        if (tc.CanConvertFrom(typeof(string))) { 
                            string text = dataNodeInfo.ValueData; 
                            try {
                            result = tc.ConvertFromInvariantString(text); 
                            } catch (NotSupportedException nse) {
                                string newMessage = SR.GetString(SR.NotSupported, typeName, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X, nse.Message);
                                XmlException xml = new XmlException(newMessage, nse, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X);
                                NotSupportedException newNse = new NotSupportedException(newMessage, xml); 
                                throw newNse;
                            } 
                        } 
                        else {
                            Debug.WriteLine("Converter for " + type.FullName + " doesn't support string conversion"); 
                        }
                    }
                }
                else { 
                    string newMessage = SR.GetString(SR.TypeLoadException, typeName, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X);
                    XmlException xml = new XmlException(newMessage, null, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X); 
                    TypeLoadException newTle = new TypeLoadException(newMessage, xml); 

                    throw newTle; 
                }
            }
            else {
                // if mimeTypeName and typeName are not filled in, the value must be a string 
                Debug.Assert(value is string, "Resource entries with no Type or MimeType must be encoded as strings");
            } 
            return result; 
        }
 
        internal DataNodeInfo GetDataNodeInfo() {
            bool shouldSerialize = true;
            if(nodeInfo != null) {
                shouldSerialize = false; 
            } else {
                nodeInfo = new DataNodeInfo(); 
            } 
            nodeInfo.Name = Name;
            nodeInfo.Comment = Comment; 

            // We always serialize if this node represents a FileRef. This is because FileRef is a public property,
            // so someone could have modified it.
            if(shouldSerialize || FileRefFullPath != null) { 
                // if we dont have a datanodeinfo it could be either
                // a direct object OR a fileref 
                if(FileRefFullPath != null) { 
                    nodeInfo.ValueData = FileRef.ToString();
                    nodeInfo.MimeType = null; 
                    nodeInfo.TypeName = typeof(ResXFileRef).AssemblyQualifiedName;
                } else {
                    // serialize to string inside the nodeInfo
                    FillDataNodeInfoFromObject(nodeInfo, value); 
                }
 
            } 
            return nodeInfo;
        } 

        /// 
        /// 
        ///    Might return the position in the resx file of the current node, if known 
        ///    otherwise, will return Point(0,0) since point is a struct
        ///  
        public Point GetNodePosition() { 
            if(nodeInfo == null) {
                return new Point(); 
            } else {
                return nodeInfo.ReaderPosition;
            }
        } 

        ///  
        ///  
        ///    Get the FQ type name for this datanode.
        ///    We return typeof(object) for ResXNullRef 
        /// 
        public string GetValueTypeName(ITypeResolutionService typeResolver) {
            // the type name here is always a FQN
            if(typeName != null && typeName.Length >0) { 
                if(typeName.Equals(typeof(ResXNullRef).AssemblyQualifiedName)) {
                    return typeof(object).AssemblyQualifiedName; 
                } else { 
                    return typeName;
                } 
            }
            string result = FileRefType;
            Type objectType = null;
            // do we have a fileref? 
            if(result != null) {
                // try to resolve this type 
                objectType = ResolveType(FileRefType, typeResolver); 
            } else if(nodeInfo != null) {
 
                // we dont have a fileref, try to resolve the type of the datanode
                result = nodeInfo.TypeName;
                // if typename is null, the default is just a string
                if(result == null || result.Length==0) { 
                    // we still dont know... do we have a mimetype? if yes, our only option is to
                    // deserialize to know what we're dealing with... very inefficient... 
                    if(nodeInfo.MimeType != null && nodeInfo.MimeType.Length > 0) { 
                        object insideObject = null;
 
                        try {
                            insideObject = GenerateObjectFromDataNodeInfo(nodeInfo, typeResolver);
                        } catch (Exception ex) { // it'd be better to catch SerializationException but the underlying type resolver
                                                // can throw things like FileNotFoundException which is kinda confusing, so I am catching all here.. 
                            if(ClientUtils.IsCriticalException(ex)) {
                                throw; 
                            } 
                            // something went wrong, type is not specified at all or stream is corrupted
                            // return system.object 
                            result = typeof(object).AssemblyQualifiedName;
                        } catch {
                            throw;
                        } 
                        if(insideObject != null) {
                            result = insideObject.GetType().AssemblyQualifiedName; 
                        } 
                    } else {
                        // no typename, no mimetype, we have a string... 
                        result = typeof(string).AssemblyQualifiedName;
                    }
                } else {
                    objectType = ResolveType(nodeInfo.TypeName, typeResolver); 
                }
            } 
            if(objectType != null) { 
                if(objectType == typeof(ResXNullRef)) {
                    result = typeof(object).AssemblyQualifiedName; 
                } else {
                    result = objectType.AssemblyQualifiedName;
                }
            } 
            return result;
        } 
 
        /// 
        ///  
        ///    Get the FQ type name for this datanode
        /// 
        public string GetValueTypeName(AssemblyName[] names) {
            return GetValueTypeName(new AssemblyNamesTypeResolutionService(names)); 
        }
 
        ///  
        /// 
        ///    Get the value contained in this datanode 
        /// 
        public object GetValue(ITypeResolutionService typeResolver) {

            if(value != null) { 
                return value;
            } 
 
            object result = null;
            if(FileRefFullPath != null) { 
                Type objectType = ResolveType(FileRefType , typeResolver);
                if(objectType != null) {
                    // we have the FQN for this type
                    if(FileRefTextEncoding != null) { 
                        fileRef = new ResXFileRef(FileRefFullPath, FileRefType, Encoding.GetEncoding(FileRefTextEncoding));
                    } else { 
                        fileRef = new ResXFileRef(FileRefFullPath, FileRefType); 
                    }
                    TypeConverter tc = TypeDescriptor.GetConverter(typeof(ResXFileRef)); 
                    result = tc.ConvertFrom(fileRef.ToString());
                } else {
                    string newMessage = SR.GetString(SR.TypeLoadExceptionShort, FileRefType);
                    TypeLoadException newTle = new TypeLoadException(newMessage); 
                    throw (newTle);
                } 
            } else if(result == null && nodeInfo.ValueData!= null) { 
                // it's embedded, we deserialize it
                result = GenerateObjectFromDataNodeInfo(nodeInfo, typeResolver); 
            } else {
                // schema is wrong and say minOccur for Value is 0,
                // but it's too late to change it...
                // we need to return null here vswhidbey 180605 
                return null;
            } 
            return result; 
        }
 
        /// 
        /// 
        ///    Get the value contained in this datanode
        ///  
        public object GetValue(AssemblyName[] names) {
            return GetValue(new AssemblyNamesTypeResolutionService(names)); 
        } 

        private static byte[] FromBase64WrappedString(string text) { 

            if (text.IndexOfAny(SpecialChars) != -1) {
                StringBuilder sb = new StringBuilder(text.Length);
                for (int i=0; i= 2) { 
                        string partialName = typeParts[0].Trim();
                        string assemblyName = typeParts[1].Trim(); 
                        partialName = partialName + ", " + assemblyName; 
                        t = typeResolver.GetType(partialName, false);
                    } 
                }
            }

            if (t == null) { 
                t = Type.GetType(typeName, false);
            } 
 
            return t;
        } 


        /// 
        ///  
        ///    Get the value contained in this datanode
        ///  
        // NOTE: No LinkDemand for SerializationFormatter necessary here, since this class already 
        // has a FullTrust LinkDemand.
        void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context) { 
            DataNodeInfo nodeInfo = GetDataNodeInfo();
            si.AddValue("Name", nodeInfo.Name, typeof(string));
            si.AddValue("Comment", nodeInfo.Comment, typeof(string));
            si.AddValue("TypeName", nodeInfo.TypeName, typeof(string)); 
            si.AddValue("MimeType", nodeInfo.MimeType, typeof(string));
            si.AddValue("ValueData", nodeInfo.ValueData, typeof(string)); 
        } 

        private ResXDataNode(SerializationInfo info, StreamingContext context) { 
            DataNodeInfo nodeInfo = new DataNodeInfo();
            nodeInfo.Name = (string)info.GetValue("Name", typeof(string));
            nodeInfo.Comment = (string)info.GetValue("Comment", typeof(string));
            nodeInfo.TypeName = (string)info.GetValue("TypeName", typeof(string)); 
            nodeInfo.MimeType = (string)info.GetValue("MimeType", typeof(string));
            nodeInfo.ValueData = (string)info.GetValue("ValueData", typeof(string)); 
            this.nodeInfo = nodeInfo; 
            InitializeDataNode(null);
        } 

    }

    internal class DataNodeInfo { 
        internal string Name;
        internal string Comment; 
        internal string TypeName; 
        internal string MimeType;
        internal string ValueData; 
        internal Point ReaderPosition; //only used to track position in the reader

        internal DataNodeInfo Clone() {
            DataNodeInfo result  = new DataNodeInfo(); 
            result.Name = this.Name;
            result.Comment = this.Comment; 
            result.TypeName = this.TypeName; 
            result.MimeType = this.MimeType;
            result.ValueData = this.ValueData; 
            result.ReaderPosition = new Point(this.ReaderPosition.X, this.ReaderPosition.Y);
            return result;
        }
    } 

    // This class implements a partial type resolver for the BinaryFormatter. 
    // This is needed to be able to read binary serialized content from older 
    // NDP types and map them to newer versions.
    // 
    internal class ResXSerializationBinder : SerializationBinder {
        private ITypeResolutionService typeResolver;

        internal ResXSerializationBinder(ITypeResolutionService typeResolver) { 
            this.typeResolver = typeResolver;
        } 
 
        public override Type BindToType(string assemblyName, string typeName) {
            if (typeResolver == null) { 
                return null;
            }

            typeName = typeName + ", " + assemblyName; 

            Type t = typeResolver.GetType(typeName); 
            if (t == null) { 
                string[] typeParts = typeName.Split(new char[] {','});
 
                // Break up the assembly name from the rest of the assembly strong name.
                // we try 1) FQN 2) FQN without a version 3) just the short name
                if (typeParts != null && typeParts.Length > 2) {
                    string partialName = typeParts[0].Trim(); 

                    for (int i = 1; i < typeParts.Length; ++i) { 
                        string s = typeParts[i].Trim(); 
                        if (!s.StartsWith("Version=") && !s.StartsWith("version=")) {
                            partialName = partialName + ", " + s; 
                        }
                    }
                    t = typeResolver.GetType(partialName);
                    if(t == null) { 
                        t = typeResolver.GetType(typeParts[0].Trim());
                    } 
                } 
            }
 
            // Binder couldn't handle it, let the default loader take over.
            return t;
        }
    } 

 
    internal class AssemblyNamesTypeResolutionService : ITypeResolutionService { 
        private AssemblyName[] names;
        private Hashtable cachedAssemblies; 

        internal AssemblyNamesTypeResolutionService(AssemblyName[] names) {
            this.names = names;
        } 

 
        public Assembly GetAssembly(AssemblyName name) { 
            return GetAssembly(name, true);
        } 

        //
        [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
        public Assembly GetAssembly(AssemblyName name, bool throwOnError) { 

            Assembly result = null; 
 
            if (cachedAssemblies == null) {
                cachedAssemblies = new Hashtable(); 
            }

            if (cachedAssemblies.Contains(name)) {
                result = cachedAssemblies[name] as Assembly; 
            }
 
            if (result == null) { 
                // try to load it first from the gac
#pragma warning disable 0618 
                //Although LoadWithPartialName is obsolete, we still have to call it: changing
                //this would be breaking in cases where people edited their resource files by
                //hand.
                result = Assembly.LoadWithPartialName(name.FullName); 
#pragma warning restore 0618
                if(result != null) { 
                    cachedAssemblies[name] = result; 
                }
                else if (names != null) { 
                    for(int i=0;i
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

#if SYSTEM_WEB  // See DevDiv 9030 
namespace System.PrivateResources { 
#else
namespace System.Resources { 
#endif

    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary; 
    using System; 
    using System.Windows.Forms;
    using System.Reflection; 
    using Microsoft.Win32;
    using System.Drawing;
    using System.IO;
    using System.Text; 
    using System.ComponentModel;
    using System.Collections; 
    using System.Runtime.CompilerServices; 
    using System.Resources;
    using System.Xml; 
    using System.ComponentModel.Design;
    using System.Globalization;
    using System.Security.Permissions;
#if SYSTEM_WEB 
    using System.Web;   // This is needed to access the SR resource strings
#endif 
 

    ///  
    /// 
    ///
    /// 
    [Serializable] 
    [PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
#if SYSTEM_WEB 
    internal sealed class ResXDataNode : ISerializable { 
#else
    public sealed class ResXDataNode : ISerializable { 
#endif

        private static readonly char[] SpecialChars = new char[]{' ', '\r', '\n'};
 
        private DataNodeInfo        nodeInfo;
 
        private string name; 
        private string comment;
#if UNUSED 
        private string mimeType;
        private string valueData;
#endif
 
        private string typeName; // is only used when we create a resxdatanode manually with an object and contains the FQN
 
        private string fileRefFullPath; 
        private string fileRefType;
        private string fileRefTextEncoding; 

        private object              value;
        private ResXFileRef         fileRef;
 
        private IFormatter binaryFormatter = null;
 
        // this is going to be used to check if a ResXDataNode is of type ResXFileRef 
        private static ITypeResolutionService internalTypeResolver = new AssemblyNamesTypeResolutionService(new AssemblyName[] { new AssemblyName("System.Windows.Forms") });
 

        // constructors

        private ResXDataNode() { 
        }
 
        //  
        // this is a deep clone
        // 
        internal ResXDataNode DeepClone() {
            ResXDataNode result = new ResXDataNode();
            result.nodeInfo = (this.nodeInfo != null) ? this.nodeInfo.Clone() : null; // nodeinfo is just made up of immutable objects, we don't need to clone it
            result.name = this.name; 
            result.comment = this.comment;
#if UNUSED 
            result.mimeType = this.mimeType; 
            result.valueData = this.valueData;
#endif 
            result.typeName = this.typeName;
            result.fileRefFullPath = this.fileRefFullPath;
            result.fileRefType = this.fileRefType;
            result.fileRefTextEncoding = this.fileRefTextEncoding; 
            result.value = this.value; // we don't clone the value, because we don't know how
            result.fileRef = (this.fileRef != null) ? this.fileRef.Clone() : null; 
            return result; 
        }
 
        /// 
        /// 
        ///
        ///  
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
        [ 
            SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "name" is the name of the param passed in. 
                                                                                                        // So we don't have to localize it.
        ] 
        public ResXDataNode(string name, object value) {
            if(name == null) {
                throw (new ArgumentNullException("name"));
            } 
            if(name.Length == 0) {
                throw (new ArgumentException("name")); 
            } 

            Type valueType = (value == null) ? typeof(object) : value.GetType(); 
            if (value != null && !valueType.IsSerializable) {
                throw new InvalidOperationException(SR.GetString(SR.NotSerializableType, name, valueType.FullName));
            } else if (value!= null) {
                this.typeName = valueType.AssemblyQualifiedName; 
            }
 
            this.name = name; 
            this.value = value;
        } 

        /// 
        /// 
        /// 
        /// 
        [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] 
        [ 
            SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "name" is the name of the param passed in.
                                                                                                        // So we don't have to localize it. 
        ]
        public ResXDataNode(string name, ResXFileRef fileRef) {
            if(name == null) {
                throw (new ArgumentNullException("name")); 
            }
            if(fileRef == null) { 
                throw (new ArgumentNullException("fileRef")); 
            }
            if(name.Length == 0) { 
                throw (new ArgumentException("name"));
            }
            this.name = name;
            this.fileRef = fileRef; 
        }
 
        internal ResXDataNode(DataNodeInfo nodeInfo, string basePath) { 
            this.nodeInfo = nodeInfo;
            InitializeDataNode(basePath); 
        }

        private void InitializeDataNode(string basePath) {
 
            // we can only use our internal type resolver here
            // because we only want to check if this is a ResXFileRef node 
            // and we can't be sure that we have a typeResolutionService that can 
            // recognize this. It's not very clean but this should work.
            Type nodeType = null; 
            if(!string.IsNullOrEmpty(nodeInfo.TypeName)) // can be null if we have a string (default for string is TypeName == null)
                nodeType = internalTypeResolver.GetType(nodeInfo.TypeName, false, true);
            if(nodeType != null && nodeType.Equals(typeof(ResXFileRef))) {
                // we have a fileref, split the value data and populate the fields 
                string[] fileRefDetails = ResXFileRef.Converter.ParseResxFileRefString(nodeInfo.ValueData);
                if(fileRefDetails != null && fileRefDetails.Length > 1) { 
                    if(!Path.IsPathRooted(fileRefDetails[0]) && basePath != null) { 
                        fileRefFullPath = Path.Combine(basePath, fileRefDetails[0]);
                    } else { 
                        fileRefFullPath = fileRefDetails[0];
                    }
                    fileRefType = fileRefDetails[1];
                    if(fileRefDetails.Length > 2) { 
                        fileRefTextEncoding = fileRefDetails[2];
                    } 
                } 
            }
        } 


        /// 
        ///  
        ///
        ///  
        public string Comment { 
            get {
                string result = comment; 
                if(result == null && nodeInfo != null) {
                    result = nodeInfo.Comment;
                }
                return (result == null ? "" : result); 
            }
            set { 
                comment= value; 
            }
        } 

        /// 
        /// 
        /// 
        /// 
        public string Name { 
            get { 
                string result = name;
                if(result == null && nodeInfo != null) { 
                    result = nodeInfo.Name;
                }
                return result;
            } 
            [
                SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "Name" is the name of the property. 
                                                                                                            // So we don't have to localize it. 
            ]
            set { 
                if(value == null) {
                    throw (new ArgumentNullException("Name"));
                }
                if(value.Length == 0) { 
                    throw (new ArgumentException("Name"));
                } 
                name = value; 
            }
        } 

#if UNUSED
        private string MimeType {
            get { 
                string result = mimeType;
                if(result == null && nodeInfo != null) { 
                    result = nodeInfo.MimeType; 
                }
                return result; 
            }
        }

        private string ValueData { 
            get {
                string result = valueData; 
                if(result == null && nodeInfo != null) { 
                    result = nodeInfo.ValueData;
                } 
                return result;
            }
        }
#endif 

        ///  
        ///  
        ///
        ///  
        public ResXFileRef FileRef {
            get {
                if(FileRefFullPath==null) {
                    return null; 
                }
                if(fileRef == null) { 
                    if(String.IsNullOrEmpty(fileRefTextEncoding)) 
                    {
                        fileRef = new ResXFileRef(FileRefFullPath, FileRefType); 
                    } else {
                        fileRef = new ResXFileRef(FileRefFullPath, FileRefType, Encoding.GetEncoding(FileRefTextEncoding));
                    }
                } 
                return fileRef;
            } 
        } 

 
        private string FileRefFullPath {
            get {
                string result = (fileRef==null ? null : fileRef.FileName);
                if(result == null) { 
                    result = fileRefFullPath;
                } 
                return result; 
            }
        } 

        private string FileRefType {
            get {
                string result = (fileRef==null ? null : fileRef.TypeName); 
                if(result == null) {
                    result = fileRefType; 
                } 
                return result;
            } 
        }

        private string FileRefTextEncoding {
            get { 
                string result = (fileRef==null ? null : (fileRef.TextFileEncoding == null ? null : fileRef.TextFileEncoding.BodyName));
                if(result == null) { 
                    result = fileRefTextEncoding; 
                }
 
                return result;
            }
        }
 

#if !SYSTEM_WEB     // System.Web does not link with the Soap assembly 
        ///  
        ///     As a performance optimization, we isolate the soap class here in a separate
        ///     function.  We don't care about the binary formatter because it lives in 
        ///     mscorlib, which is already loaded.  The soap formatter lives in a separate
        ///     assembly, however, so there is value in preventing it from needlessly
        ///     being loaded.
        ///  
        [MethodImplAttribute(MethodImplOptions.NoInlining)]
        private IFormatter CreateSoapFormatter() { 
            return new System.Runtime.Serialization.Formatters.Soap.SoapFormatter(); 
        }
#endif 


        private static string ToBase64WrappedString(byte[] data) {
            const int lineWrap = 80; 
            const string crlf = "\r\n";
            const string prefix = "        "; 
            string raw = Convert.ToBase64String(data); 
            if (raw.Length > lineWrap) {
                StringBuilder output = new StringBuilder(raw.Length + (raw.Length / lineWrap) * 3); // word wrap on lineWrap chars, \r\n 
                int current = 0;
                for (; current < raw.Length - lineWrap; current+=lineWrap) {
                    output.Append(crlf);
                    output.Append(prefix); 
                    output.Append(raw, current, lineWrap);
                } 
                output.Append(crlf); 
                output.Append(prefix);
                output.Append(raw, current, raw.Length - current); 
                output.Append(crlf);
                return output.ToString();
            }
            else { 
                return raw;
            } 
        } 

        private void FillDataNodeInfoFromObject(DataNodeInfo nodeInfo, object value) { 
            if (value is string) {
                nodeInfo.ValueData = (string)value;
                if(value == null) {
                    nodeInfo.TypeName = typeof(ResXNullRef).AssemblyQualifiedName; 
                }
            } 
            else if (value is byte[]) { 
                nodeInfo.ValueData = ToBase64WrappedString((byte[])value);
                nodeInfo.TypeName = typeof(byte[]).AssemblyQualifiedName; 
            }
            else {
                Type valueType = (value == null) ? typeof(object) : value.GetType();
                if (value != null && !valueType.IsSerializable) { 
                    throw new InvalidOperationException(SR.GetString(SR.NotSerializableType, name, valueType.FullName));
                } 
                TypeConverter tc = TypeDescriptor.GetConverter(valueType); 
                bool toString = tc.CanConvertTo(typeof(string));
                bool fromString = tc.CanConvertFrom(typeof(string)); 
                try {
                    if (toString && fromString) {
                        nodeInfo.ValueData = tc.ConvertToInvariantString(value);
                        nodeInfo.TypeName = valueType.AssemblyQualifiedName; 
                        return;
                    } 
                } 
                catch (Exception ex) {
                    // Some custom type converters will throw in ConvertTo(string) 
                    // to indicate that this object should be serialized through ISeriazable
                    // instead of as a string. This is semi-wrong, but something we will have to
                    // live with to allow user created Cursors to be serializable.
                    if (ClientUtils.IsSecurityOrCriticalException(ex)) { 
                        throw;
                    } 
                } 
                catch {
                } 

                bool toByteArray = tc.CanConvertTo(typeof(byte[]));
                bool fromByteArray = tc.CanConvertFrom(typeof(byte[]));
                if (toByteArray && fromByteArray) { 
                    byte[] data = (byte[])tc.ConvertTo(value, typeof(byte[]));
                    string text = ToBase64WrappedString(data); 
                    nodeInfo.ValueData = text; 
                    nodeInfo.MimeType = ResXResourceWriter.ByteArraySerializedObjectMimeType;
                    nodeInfo.TypeName = valueType.AssemblyQualifiedName; 
                    return;
                }

                if (value == null) { 
                    nodeInfo.ValueData = string.Empty;
                    nodeInfo.TypeName = typeof(ResXNullRef).AssemblyQualifiedName; 
                } 
                else {
                    if (binaryFormatter == null) { 
                        binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                    }

                    MemoryStream ms = new MemoryStream(); 
                    if (binaryFormatter == null) {
                        binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
                    } 
                    IFormatter formatter = binaryFormatter;
                    formatter.Serialize(ms, value); 
                    string text = ToBase64WrappedString(ms.ToArray());
                    nodeInfo.ValueData = text;
                    nodeInfo.MimeType = ResXResourceWriter.DefaultSerializedObjectMimeType;
                } 
            }
 
        } 

 
        private object GenerateObjectFromDataNodeInfo(DataNodeInfo dataNodeInfo, ITypeResolutionService typeResolver) {
            object result = null;
            string mimeTypeName = dataNodeInfo.MimeType;
            // default behavior: if we dont have a type name, it's a string 
            string typeName = (dataNodeInfo.TypeName == null || dataNodeInfo.TypeName.Length==0 ? typeof(string).AssemblyQualifiedName : dataNodeInfo.TypeName);
 
            if (mimeTypeName != null && mimeTypeName.Length > 0) { 
                if (String.Equals(mimeTypeName, ResXResourceWriter.BinSerializedObjectMimeType)
                    || String.Equals(mimeTypeName, ResXResourceWriter.Beta2CompatSerializedObjectMimeType) 
                    || String.Equals(mimeTypeName, ResXResourceWriter.CompatBinSerializedObjectMimeType)) {
                    string text = dataNodeInfo.ValueData;
                    byte[] serializedData;
                    serializedData = FromBase64WrappedString(text); 

                    if (binaryFormatter == null) { 
                        binaryFormatter = new BinaryFormatter(); 
                        binaryFormatter.Binder = new ResXSerializationBinder(typeResolver);
                    } 
                    IFormatter formatter = binaryFormatter;
                    if (serializedData != null && serializedData.Length > 0) {
                        result = formatter.Deserialize(new MemoryStream(serializedData));
                        if (result is ResXNullRef) { 
                            result = null;
                        } 
                    } 
                }
#if !SYSTEM_WEB // System.Web does not link with the Soap assembly 
                else if (String.Equals(mimeTypeName, ResXResourceWriter.SoapSerializedObjectMimeType)
                         || String.Equals(mimeTypeName, ResXResourceWriter.CompatSoapSerializedObjectMimeType)) {
                    string text = dataNodeInfo.ValueData;
                    byte[] serializedData; 
                    serializedData = FromBase64WrappedString(text);
 
                    if (serializedData != null && serializedData.Length > 0) { 

                        // Performance : don't inline a new SoapFormatter here.  That will always bring in 
                        //               the soap assembly, which we don't want.  Throw this in another
                        //               function so the class doesn't have to get loaded.
                        //
                        IFormatter formatter = CreateSoapFormatter(); 
                        result = formatter.Deserialize(new MemoryStream(serializedData));
                        if (result is ResXNullRef) { 
                            result = null; 
                        }
                    } 
                }
#endif
                else if (String.Equals(mimeTypeName, ResXResourceWriter.ByteArraySerializedObjectMimeType)) {
                    if (typeName != null && typeName.Length > 0) { 
                        Type type = ResolveType(typeName, typeResolver);
                        if (type != null) { 
                            TypeConverter tc = TypeDescriptor.GetConverter(type); 
                            if (tc.CanConvertFrom(typeof(byte[]))) {
                                string text = dataNodeInfo.ValueData; 
                                byte[] serializedData;
                                serializedData = FromBase64WrappedString(text);

                                if (serializedData != null) { 
                                    result = tc.ConvertFrom(serializedData);
                                } 
                            } 
                        }
                        else { 
                            string newMessage = SR.GetString(SR.TypeLoadException, typeName, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X);
                            XmlException xml = new XmlException(newMessage, null, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X);
                            TypeLoadException newTle = new TypeLoadException(newMessage, xml);
 
                            throw newTle;
                        } 
                    } 
                }
            } 
            else if (typeName != null && typeName.Length > 0) {
                Type type = ResolveType(typeName, typeResolver);
                if (type != null) {
                    if (type == typeof(ResXNullRef)) { 
                        result = null;
                    } 
                    else if (typeName.IndexOf("System.Byte[]") != -1 && typeName.IndexOf("mscorlib") != -1) { 
                        // Handle byte[]'s, which are stored as base-64 encoded strings.
                        // We can't hard-code byte[] type name due to version number 
                        // updates & potential whitespace issues with ResX files.
                        result = FromBase64WrappedString(dataNodeInfo.ValueData);
                    }
                    else { 
                        TypeConverter tc = TypeDescriptor.GetConverter(type);
                        if (tc.CanConvertFrom(typeof(string))) { 
                            string text = dataNodeInfo.ValueData; 
                            try {
                            result = tc.ConvertFromInvariantString(text); 
                            } catch (NotSupportedException nse) {
                                string newMessage = SR.GetString(SR.NotSupported, typeName, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X, nse.Message);
                                XmlException xml = new XmlException(newMessage, nse, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X);
                                NotSupportedException newNse = new NotSupportedException(newMessage, xml); 
                                throw newNse;
                            } 
                        } 
                        else {
                            Debug.WriteLine("Converter for " + type.FullName + " doesn't support string conversion"); 
                        }
                    }
                }
                else { 
                    string newMessage = SR.GetString(SR.TypeLoadException, typeName, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X);
                    XmlException xml = new XmlException(newMessage, null, dataNodeInfo.ReaderPosition.Y, dataNodeInfo.ReaderPosition.X); 
                    TypeLoadException newTle = new TypeLoadException(newMessage, xml); 

                    throw newTle; 
                }
            }
            else {
                // if mimeTypeName and typeName are not filled in, the value must be a string 
                Debug.Assert(value is string, "Resource entries with no Type or MimeType must be encoded as strings");
            } 
            return result; 
        }
 
        internal DataNodeInfo GetDataNodeInfo() {
            bool shouldSerialize = true;
            if(nodeInfo != null) {
                shouldSerialize = false; 
            } else {
                nodeInfo = new DataNodeInfo(); 
            } 
            nodeInfo.Name = Name;
            nodeInfo.Comment = Comment; 

            // We always serialize if this node represents a FileRef. This is because FileRef is a public property,
            // so someone could have modified it.
            if(shouldSerialize || FileRefFullPath != null) { 
                // if we dont have a datanodeinfo it could be either
                // a direct object OR a fileref 
                if(FileRefFullPath != null) { 
                    nodeInfo.ValueData = FileRef.ToString();
                    nodeInfo.MimeType = null; 
                    nodeInfo.TypeName = typeof(ResXFileRef).AssemblyQualifiedName;
                } else {
                    // serialize to string inside the nodeInfo
                    FillDataNodeInfoFromObject(nodeInfo, value); 
                }
 
            } 
            return nodeInfo;
        } 

        /// 
        /// 
        ///    Might return the position in the resx file of the current node, if known 
        ///    otherwise, will return Point(0,0) since point is a struct
        ///  
        public Point GetNodePosition() { 
            if(nodeInfo == null) {
                return new Point(); 
            } else {
                return nodeInfo.ReaderPosition;
            }
        } 

        ///  
        ///  
        ///    Get the FQ type name for this datanode.
        ///    We return typeof(object) for ResXNullRef 
        /// 
        public string GetValueTypeName(ITypeResolutionService typeResolver) {
            // the type name here is always a FQN
            if(typeName != null && typeName.Length >0) { 
                if(typeName.Equals(typeof(ResXNullRef).AssemblyQualifiedName)) {
                    return typeof(object).AssemblyQualifiedName; 
                } else { 
                    return typeName;
                } 
            }
            string result = FileRefType;
            Type objectType = null;
            // do we have a fileref? 
            if(result != null) {
                // try to resolve this type 
                objectType = ResolveType(FileRefType, typeResolver); 
            } else if(nodeInfo != null) {
 
                // we dont have a fileref, try to resolve the type of the datanode
                result = nodeInfo.TypeName;
                // if typename is null, the default is just a string
                if(result == null || result.Length==0) { 
                    // we still dont know... do we have a mimetype? if yes, our only option is to
                    // deserialize to know what we're dealing with... very inefficient... 
                    if(nodeInfo.MimeType != null && nodeInfo.MimeType.Length > 0) { 
                        object insideObject = null;
 
                        try {
                            insideObject = GenerateObjectFromDataNodeInfo(nodeInfo, typeResolver);
                        } catch (Exception ex) { // it'd be better to catch SerializationException but the underlying type resolver
                                                // can throw things like FileNotFoundException which is kinda confusing, so I am catching all here.. 
                            if(ClientUtils.IsCriticalException(ex)) {
                                throw; 
                            } 
                            // something went wrong, type is not specified at all or stream is corrupted
                            // return system.object 
                            result = typeof(object).AssemblyQualifiedName;
                        } catch {
                            throw;
                        } 
                        if(insideObject != null) {
                            result = insideObject.GetType().AssemblyQualifiedName; 
                        } 
                    } else {
                        // no typename, no mimetype, we have a string... 
                        result = typeof(string).AssemblyQualifiedName;
                    }
                } else {
                    objectType = ResolveType(nodeInfo.TypeName, typeResolver); 
                }
            } 
            if(objectType != null) { 
                if(objectType == typeof(ResXNullRef)) {
                    result = typeof(object).AssemblyQualifiedName; 
                } else {
                    result = objectType.AssemblyQualifiedName;
                }
            } 
            return result;
        } 
 
        /// 
        ///  
        ///    Get the FQ type name for this datanode
        /// 
        public string GetValueTypeName(AssemblyName[] names) {
            return GetValueTypeName(new AssemblyNamesTypeResolutionService(names)); 
        }
 
        ///  
        /// 
        ///    Get the value contained in this datanode 
        /// 
        public object GetValue(ITypeResolutionService typeResolver) {

            if(value != null) { 
                return value;
            } 
 
            object result = null;
            if(FileRefFullPath != null) { 
                Type objectType = ResolveType(FileRefType , typeResolver);
                if(objectType != null) {
                    // we have the FQN for this type
                    if(FileRefTextEncoding != null) { 
                        fileRef = new ResXFileRef(FileRefFullPath, FileRefType, Encoding.GetEncoding(FileRefTextEncoding));
                    } else { 
                        fileRef = new ResXFileRef(FileRefFullPath, FileRefType); 
                    }
                    TypeConverter tc = TypeDescriptor.GetConverter(typeof(ResXFileRef)); 
                    result = tc.ConvertFrom(fileRef.ToString());
                } else {
                    string newMessage = SR.GetString(SR.TypeLoadExceptionShort, FileRefType);
                    TypeLoadException newTle = new TypeLoadException(newMessage); 
                    throw (newTle);
                } 
            } else if(result == null && nodeInfo.ValueData!= null) { 
                // it's embedded, we deserialize it
                result = GenerateObjectFromDataNodeInfo(nodeInfo, typeResolver); 
            } else {
                // schema is wrong and say minOccur for Value is 0,
                // but it's too late to change it...
                // we need to return null here vswhidbey 180605 
                return null;
            } 
            return result; 
        }
 
        /// 
        /// 
        ///    Get the value contained in this datanode
        ///  
        public object GetValue(AssemblyName[] names) {
            return GetValue(new AssemblyNamesTypeResolutionService(names)); 
        } 

        private static byte[] FromBase64WrappedString(string text) { 

            if (text.IndexOfAny(SpecialChars) != -1) {
                StringBuilder sb = new StringBuilder(text.Length);
                for (int i=0; i= 2) { 
                        string partialName = typeParts[0].Trim();
                        string assemblyName = typeParts[1].Trim(); 
                        partialName = partialName + ", " + assemblyName; 
                        t = typeResolver.GetType(partialName, false);
                    } 
                }
            }

            if (t == null) { 
                t = Type.GetType(typeName, false);
            } 
 
            return t;
        } 


        /// 
        ///  
        ///    Get the value contained in this datanode
        ///  
        // NOTE: No LinkDemand for SerializationFormatter necessary here, since this class already 
        // has a FullTrust LinkDemand.
        void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context) { 
            DataNodeInfo nodeInfo = GetDataNodeInfo();
            si.AddValue("Name", nodeInfo.Name, typeof(string));
            si.AddValue("Comment", nodeInfo.Comment, typeof(string));
            si.AddValue("TypeName", nodeInfo.TypeName, typeof(string)); 
            si.AddValue("MimeType", nodeInfo.MimeType, typeof(string));
            si.AddValue("ValueData", nodeInfo.ValueData, typeof(string)); 
        } 

        private ResXDataNode(SerializationInfo info, StreamingContext context) { 
            DataNodeInfo nodeInfo = new DataNodeInfo();
            nodeInfo.Name = (string)info.GetValue("Name", typeof(string));
            nodeInfo.Comment = (string)info.GetValue("Comment", typeof(string));
            nodeInfo.TypeName = (string)info.GetValue("TypeName", typeof(string)); 
            nodeInfo.MimeType = (string)info.GetValue("MimeType", typeof(string));
            nodeInfo.ValueData = (string)info.GetValue("ValueData", typeof(string)); 
            this.nodeInfo = nodeInfo; 
            InitializeDataNode(null);
        } 

    }

    internal class DataNodeInfo { 
        internal string Name;
        internal string Comment; 
        internal string TypeName; 
        internal string MimeType;
        internal string ValueData; 
        internal Point ReaderPosition; //only used to track position in the reader

        internal DataNodeInfo Clone() {
            DataNodeInfo result  = new DataNodeInfo(); 
            result.Name = this.Name;
            result.Comment = this.Comment; 
            result.TypeName = this.TypeName; 
            result.MimeType = this.MimeType;
            result.ValueData = this.ValueData; 
            result.ReaderPosition = new Point(this.ReaderPosition.X, this.ReaderPosition.Y);
            return result;
        }
    } 

    // This class implements a partial type resolver for the BinaryFormatter. 
    // This is needed to be able to read binary serialized content from older 
    // NDP types and map them to newer versions.
    // 
    internal class ResXSerializationBinder : SerializationBinder {
        private ITypeResolutionService typeResolver;

        internal ResXSerializationBinder(ITypeResolutionService typeResolver) { 
            this.typeResolver = typeResolver;
        } 
 
        public override Type BindToType(string assemblyName, string typeName) {
            if (typeResolver == null) { 
                return null;
            }

            typeName = typeName + ", " + assemblyName; 

            Type t = typeResolver.GetType(typeName); 
            if (t == null) { 
                string[] typeParts = typeName.Split(new char[] {','});
 
                // Break up the assembly name from the rest of the assembly strong name.
                // we try 1) FQN 2) FQN without a version 3) just the short name
                if (typeParts != null && typeParts.Length > 2) {
                    string partialName = typeParts[0].Trim(); 

                    for (int i = 1; i < typeParts.Length; ++i) { 
                        string s = typeParts[i].Trim(); 
                        if (!s.StartsWith("Version=") && !s.StartsWith("version=")) {
                            partialName = partialName + ", " + s; 
                        }
                    }
                    t = typeResolver.GetType(partialName);
                    if(t == null) { 
                        t = typeResolver.GetType(typeParts[0].Trim());
                    } 
                } 
            }
 
            // Binder couldn't handle it, let the default loader take over.
            return t;
        }
    } 

 
    internal class AssemblyNamesTypeResolutionService : ITypeResolutionService { 
        private AssemblyName[] names;
        private Hashtable cachedAssemblies; 

        internal AssemblyNamesTypeResolutionService(AssemblyName[] names) {
            this.names = names;
        } 

 
        public Assembly GetAssembly(AssemblyName name) { 
            return GetAssembly(name, true);
        } 

        //
        [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
        public Assembly GetAssembly(AssemblyName name, bool throwOnError) { 

            Assembly result = null; 
 
            if (cachedAssemblies == null) {
                cachedAssemblies = new Hashtable(); 
            }

            if (cachedAssemblies.Contains(name)) {
                result = cachedAssemblies[name] as Assembly; 
            }
 
            if (result == null) { 
                // try to load it first from the gac
#pragma warning disable 0618 
                //Although LoadWithPartialName is obsolete, we still have to call it: changing
                //this would be breaking in cases where people edited their resource files by
                //hand.
                result = Assembly.LoadWithPartialName(name.FullName); 
#pragma warning restore 0618
                if(result != null) { 
                    cachedAssemblies[name] = result; 
                }
                else if (names != null) { 
                    for(int i=0;i

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK