public ResXDataNode(string name, object value, Func <Type, string> typeNameConverter) { if (name == null) { throw (new ArgumentNullException(nameof(name))); } if (name.Length == 0) { throw (new ArgumentException(nameof(name))); } this.typeNameConverter = typeNameConverter; Type valueType = (value == null) ? typeof(object) : value.GetType(); if (value != null && !valueType.IsSerializable) { throw new InvalidOperationException(string.Format(SR.NotSerializableType, name, valueType.FullName)); } if (value != null) { typeName = MultitargetUtil.GetAssemblyQualifiedName(valueType, this.typeNameConverter); } this.name = name; this.value = value; }
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 = MultitargetUtil.GetAssemblyQualifiedName(typeof(ResXFileRef), typeNameConverter); } else { // serialize to string inside the nodeInfo FillDataNodeInfoFromObject(nodeInfo, value); } } return(nodeInfo); }
/// <summary> /// Adds a string resource to the resources. /// </summary> private void AddDataRow(string elementName, string name, string value) { // if it's a null string, set it here as a resxnullref string typeName = value == null ? MultitargetUtil.GetAssemblyQualifiedName(typeof(ResXNullRef), typeNameConverter) : null; AddDataRow(elementName, name, value, typeName, null, null); }
// // Get the multitarget-aware string representation for the give type. public override void BindToName(Type serializedType, out string assemblyName, out string typeName) { // Normally we don't change typeName when changing the target framework, // only assembly version or assembly name might change, thus we are setting // typeName only if it changed with the framework version. // If binder passes in a null, BinaryFormatter will use the original value or // for un-serializable types will redirect to another type. // For example: // // Encoding = Encoding.GetEncoding("shift_jis"); // public Encoding Encoding { get; set; } // property type (Encoding) is abstract, but the value is instantiated to a specific class, // and should be serialized as a specific class in order to be able to instantiate the result. // // another example are singleton objects like DBNull.Value which are serialized by System.UnitySerializationHolder typeName = null; if (typeNameConverter != null) { string assemblyQualifiedTypeName = MultitargetUtil.GetAssemblyQualifiedName(serializedType, typeNameConverter); if (!string.IsNullOrEmpty(assemblyQualifiedTypeName)) { int pos = assemblyQualifiedTypeName.IndexOf(','); if (pos > 0 && pos < assemblyQualifiedTypeName.Length - 1) { assemblyName = assemblyQualifiedTypeName.Substring(pos + 1).TrimStart(); string newTypeName = assemblyQualifiedTypeName.Substring(0, pos); if (!string.Equals(newTypeName, serializedType.FullName, StringComparison.InvariantCulture)) { typeName = newTypeName; } return; } } } base.BindToName(serializedType, out assemblyName, out typeName); }
private string TypeNameWithAssembly(Type type) { string result = MultitargetUtil.GetAssemblyQualifiedName(type, typeNameConverter); return(result); }
/// <summary> /// Adds a new row to the Resources table. This helper is used because /// we want to always late bind to the columns for greater flexibility. /// </summary> private void AddDataRow(string elementName, string name, string value, string type, string mimeType, string comment) { if (hasBeenSaved) { throw new InvalidOperationException(SR.ResXResourceWriterSaved); } string alias = null; if (!string.IsNullOrEmpty(type) && elementName == DataStr) { string assemblyName = GetFullName(type); if (string.IsNullOrEmpty(assemblyName)) { try { Type typeObject = Type.GetType(type); if (typeObject == typeof(string)) { type = null; } else if (typeObject != null) { assemblyName = GetFullName(MultitargetUtil.GetAssemblyQualifiedName(typeObject, typeNameConverter)); alias = GetAliasFromName(new AssemblyName(assemblyName)); } } catch { } } else { alias = GetAliasFromName(new AssemblyName(GetFullName(type))); } //AddAssemblyRow(AssemblyStr, alias, GetFullName(type)); } Writer.WriteStartElement(elementName); { Writer.WriteAttributeString(NameStr, name); if (!string.IsNullOrEmpty(alias) && !string.IsNullOrEmpty(type) && elementName == DataStr) { // CHANGE: we still output version information. This might have // to change in 3.2 string typeName = GetTypeName(type); string typeValue = typeName + ", " + alias; Writer.WriteAttributeString(TypeStr, typeValue); } else { if (type != null) { Writer.WriteAttributeString(TypeStr, type); } } if (mimeType != null) { Writer.WriteAttributeString(MimeTypeStr, mimeType); } if ((type == null && mimeType == null) || (type != null && type.StartsWith("System.Char", StringComparison.Ordinal))) { Writer.WriteAttributeString("xml", "space", null, "preserve"); } Writer.WriteStartElement(ValueStr); { if (!string.IsNullOrEmpty(value)) { Writer.WriteString(value); } } Writer.WriteEndElement(); if (!string.IsNullOrEmpty(comment)) { Writer.WriteStartElement(CommentStr); { Writer.WriteString(comment); } Writer.WriteEndElement(); } } Writer.WriteEndElement(); }
private void InitializeWriter() { if (xmlTextWriter == null) { // bool writeHeaderRequired = false; if (textWriter != null) { textWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); writeHeaderRequired = true; xmlTextWriter = new XmlTextWriter(textWriter); } else if (stream != null) { xmlTextWriter = new XmlTextWriter(stream, System.Text.Encoding.UTF8); } else { Debug.Assert(fileName != null, "Nothing to output to"); xmlTextWriter = new XmlTextWriter(fileName, System.Text.Encoding.UTF8); } xmlTextWriter.Formatting = Formatting.Indented; xmlTextWriter.Indentation = 2; if (!writeHeaderRequired) { xmlTextWriter.WriteStartDocument(); // writes <?xml version="1.0" encoding="utf-8"?> } } else { xmlTextWriter.WriteStartDocument(); } xmlTextWriter.WriteStartElement("root"); XmlTextReader reader = new XmlTextReader(new StringReader(ResourceSchema)) { WhitespaceHandling = WhitespaceHandling.None }; xmlTextWriter.WriteNode(reader, true); xmlTextWriter.WriteStartElement(ResHeaderStr); { xmlTextWriter.WriteAttributeString(NameStr, ResMimeTypeStr); xmlTextWriter.WriteStartElement(ValueStr); { xmlTextWriter.WriteString(ResMimeType); } xmlTextWriter.WriteEndElement(); } xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement(ResHeaderStr); { xmlTextWriter.WriteAttributeString(NameStr, VersionStr); xmlTextWriter.WriteStartElement(ValueStr); { xmlTextWriter.WriteString(Version); } xmlTextWriter.WriteEndElement(); } xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement(ResHeaderStr); { xmlTextWriter.WriteAttributeString(NameStr, ReaderStr); xmlTextWriter.WriteStartElement(ValueStr); { xmlTextWriter.WriteString(MultitargetUtil.GetAssemblyQualifiedName(typeof(ResXResourceReader), typeNameConverter)); } xmlTextWriter.WriteEndElement(); } xmlTextWriter.WriteEndElement(); xmlTextWriter.WriteStartElement(ResHeaderStr); { xmlTextWriter.WriteAttributeString(NameStr, WriterStr); xmlTextWriter.WriteStartElement(ValueStr); { xmlTextWriter.WriteString(MultitargetUtil.GetAssemblyQualifiedName(typeof(ResXResourceWriter), typeNameConverter)); } xmlTextWriter.WriteEndElement(); } xmlTextWriter.WriteEndElement(); initialized = true; }
/// <summary> /// Get the FQ type name for this datanode. /// We return typeof(object) for ResXNullRef /// </summary> public string GetValueTypeName(ITypeResolutionService typeResolver) { // the type name here is always a FQN if (!string.IsNullOrEmpty(typeName)) { return (typeName == MultitargetUtil.GetAssemblyQualifiedName(typeof(ResXNullRef), typeNameConverter) ? MultitargetUtil.GetAssemblyQualifiedName(typeof(object), typeNameConverter) : 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 (string.IsNullOrEmpty(result)) { // 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 (!string.IsNullOrEmpty(nodeInfo.MimeType)) { 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 = MultitargetUtil.GetAssemblyQualifiedName(typeof(object), typeNameConverter); } if (insideObject != null) { result = MultitargetUtil.GetAssemblyQualifiedName(insideObject.GetType(), typeNameConverter); } } else { // no typename, no mimetype, we have a string... result = MultitargetUtil.GetAssemblyQualifiedName(typeof(string), typeNameConverter); } } else { objectType = ResolveType(nodeInfo.TypeName, typeResolver); } } if (objectType != null) { if (objectType == typeof(ResXNullRef)) { result = MultitargetUtil.GetAssemblyQualifiedName(typeof(object), typeNameConverter); } else { result = MultitargetUtil.GetAssemblyQualifiedName(objectType, typeNameConverter); } } return(result); }
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 = string.IsNullOrEmpty(dataNodeInfo.TypeName) ? MultitargetUtil.GetAssemblyQualifiedName(typeof(string), typeNameConverter) : dataNodeInfo.TypeName; if (!string.IsNullOrEmpty(mimeTypeName)) { if (string.Equals(mimeTypeName, ResXResourceWriter.BinSerializedObjectMimeType)) { string text = dataNodeInfo.ValueData; byte[] serializedData = FromBase64WrappedString(text); if (binaryFormatter == null) { binaryFormatter = new 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; } } } else if (string.Equals(mimeTypeName, ResXResourceWriter.ByteArraySerializedObjectMimeType)) { if (!string.IsNullOrEmpty(typeName)) { Type type = ResolveType(typeName, typeResolver); if (type != null) { TypeConverter tc = TypeDescriptor.GetConverter(type); if (tc.CanConvertFrom(typeof(byte[]))) { string text = dataNodeInfo.ValueData; byte[] serializedData = FromBase64WrappedString(text); if (serializedData != null) { result = tc.ConvertFrom(serializedData); } } } else { string newMessage = string.Format(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 (!string.IsNullOrEmpty(typeName)) { 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 = string.Format(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 = string.Format(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); }
private void FillDataNodeInfoFromObject(DataNodeInfo nodeInfo, object value) { if (value is CultureInfo ci) { // special-case CultureInfo, cannot use CultureInfoConverter for serialization nodeInfo.ValueData = ci.Name; nodeInfo.TypeName = MultitargetUtil.GetAssemblyQualifiedName(typeof(CultureInfo), typeNameConverter); } else if (value is string str) { nodeInfo.ValueData = str; } else if (value is byte[] bytes) { nodeInfo.ValueData = ToBase64WrappedString(bytes); nodeInfo.TypeName = MultitargetUtil.GetAssemblyQualifiedName(typeof(byte[]), typeNameConverter); } else { Type valueType = (value == null) ? typeof(object) : value.GetType(); if (value != null && !valueType.IsSerializable) { throw new InvalidOperationException(string.Format(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 = MultitargetUtil.GetAssemblyQualifiedName(valueType, typeNameConverter); 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; } } bool toByteArray = tc.CanConvertTo(typeof(byte[])); bool fromByteArray = tc.CanConvertFrom(typeof(byte[])); if (toByteArray && fromByteArray) { byte[] data = (byte[])tc.ConvertTo(value, typeof(byte[])); nodeInfo.ValueData = ToBase64WrappedString(data); nodeInfo.MimeType = ResXResourceWriter.ByteArraySerializedObjectMimeType; nodeInfo.TypeName = MultitargetUtil.GetAssemblyQualifiedName(valueType, typeNameConverter); return; } if (value == null) { nodeInfo.ValueData = string.Empty; nodeInfo.TypeName = MultitargetUtil.GetAssemblyQualifiedName(typeof(ResXNullRef), typeNameConverter); } else { if (binaryFormatter == null) { binaryFormatter = new BinaryFormatter { Binder = new ResXSerializationBinder(typeNameConverter) }; } using (MemoryStream ms = new MemoryStream()) { binaryFormatter.Serialize(ms, value); nodeInfo.ValueData = ToBase64WrappedString(ms.ToArray()); } nodeInfo.MimeType = ResXResourceWriter.DefaultSerializedObjectMimeType; } } }