/// <summary> /// Adds a resource to the resources. If the resource is a string, /// it will be saved that way, otherwise it will be serialized /// and stored as in binary. /// </summary> private void AddDataRow(string elementName, string name, object value) { Debug.WriteLineIf(ResValueProviderSwitch.TraceVerbose, " resx: adding resource " + name); if (value is string) { AddDataRow(elementName, name, (string)value); } else if (value is byte[]) { AddDataRow(elementName, name, (byte[])value); } else if (value is ResXFileRef) { ResXFileRef fileRef = (ResXFileRef)value; ResXDataNode node = new ResXDataNode(name, fileRef, this.typeNameConverter); if (fileRef != null) { fileRef.MakeFilePathRelative(BasePath); } DataNodeInfo info = node.GetDataNodeInfo(); AddDataRow(elementName, info.Name, info.ValueData, info.TypeName, info.MimeType, info.Comment); } else { ResXDataNode node = new ResXDataNode(name, value, this.typeNameConverter); DataNodeInfo info = node.GetDataNodeInfo(); AddDataRow(elementName, info.Name, info.ValueData, info.TypeName, info.MimeType, info.Comment); } }
/// <summary> /// Adds a string resource to the resources. /// </summary> public void AddResource(ResXDataNode node) { // we're modifying the node as we're adding it to the resxwriter // this is BAD, so we clone it. adding it to a writer doesnt change it // we're messing with a copy ResXDataNode nodeClone = node.DeepClone(); ResXFileRef fileRef = nodeClone.FileRef; string modifiedBasePath = BasePath; if (!string.IsNullOrEmpty(modifiedBasePath)) { if (!(modifiedBasePath.EndsWith("\\"))) { modifiedBasePath += "\\"; } if (fileRef != null) { fileRef.MakeFilePathRelative(modifiedBasePath); } } DataNodeInfo info = nodeClone.GetDataNodeInfo(); AddDataRow(DataStr, info.Name, info.ValueData, info.TypeName, info.MimeType, info.Comment); }
// <summary> // this is a deep clone //</summary> internal ResXDataNode DeepClone() { ResXDataNode result = new ResXDataNode { // nodeinfo is just made up of immutable objects, we don't need to clone it nodeInfo = nodeInfo?.Clone(), name = name, comment = comment, typeName = typeName, fileRefFullPath = fileRefFullPath, fileRefType = fileRefType, fileRefTextEncoding = fileRefTextEncoding, value = value, fileRef = fileRef?.Clone(), typeNameConverter = typeNameConverter }; // we don't clone the value, because we don't know how return(result); }
private void ParseDataNode(XmlTextReader nodeReader, bool isMetaData) { DataNodeInfo nodeInfo = new DataNodeInfo(); nodeInfo.Name = nodeReader[ResXResourceWriter.NameStr]; string typeName = nodeReader[ResXResourceWriter.TypeStr]; string alias = null; AssemblyName assemblyName = null; if (!string.IsNullOrEmpty(typeName)) { alias = GetAliasFromTypeName(typeName); } if (!string.IsNullOrEmpty(alias)) { assemblyName = aliasResolver.ResolveAlias(alias); } if (assemblyName != null) { nodeInfo.TypeName = GetTypeFromTypeName(typeName) + ", " + assemblyName.FullName; } else { nodeInfo.TypeName = nodeReader[ResXResourceWriter.TypeStr]; } nodeInfo.MimeType = nodeReader[ResXResourceWriter.MimeTypeStr]; bool finishedReadingDataNode = false; nodeInfo.ReaderPosition = GetPosition(nodeReader); while (!finishedReadingDataNode && nodeReader.Read()) { if (nodeReader.NodeType == XmlNodeType.EndElement && (nodeReader.LocalName.Equals(ResXResourceWriter.DataStr) || nodeReader.LocalName.Equals(ResXResourceWriter.MetadataStr))) { // we just found </data>, quit or </metadata> finishedReadingDataNode = true; } else { // could be a <value> or a <comment> if (nodeReader.NodeType == XmlNodeType.Element) { if (nodeReader.Name.Equals(ResXResourceWriter.ValueStr)) { WhitespaceHandling oldValue = nodeReader.WhitespaceHandling; try { // based on the documentation at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemxmlxmltextreaderclasswhitespacehandlingtopic.asp // this is ok because: // "Because the XmlTextReader does not have DTD information available to it, // SignificantWhitepsace nodes are only returned within the an xml:space='preserve' scope." // the xml:space would not be present for anything else than string and char (see ResXResourceWriter) // so this would not cause any breaking change while reading data from Everett (we never outputed // xml:space then) or from whidbey that is not specifically either a string or a char. // However please note that manually editing a resx file in Everett and in Whidbey because of the addition // of xml:space=preserve might have different consequences... nodeReader.WhitespaceHandling = WhitespaceHandling.Significant; nodeInfo.ValueData = nodeReader.ReadString(); } finally { nodeReader.WhitespaceHandling = oldValue; } } else if (nodeReader.Name.Equals(ResXResourceWriter.CommentStr)) { nodeInfo.Comment = nodeReader.ReadString(); } } else { // weird, no <xxxx> tag, just the inside of <data> as text nodeInfo.ValueData = nodeReader.Value.Trim(); } } } if (nodeInfo.Name == null) { throw new ArgumentException(string.Format(SR.InvalidResXResourceNoName, nodeInfo.ValueData)); } ResXDataNode dataNode = new ResXDataNode(nodeInfo, BasePath); if (UseResXDataNodes) { resData[nodeInfo.Name] = dataNode; } else { IDictionary data = (isMetaData ? resMetadata : resData); if (assemblyNames == null) { data[nodeInfo.Name] = dataNode.GetValue(typeResolver); } else { data[nodeInfo.Name] = dataNode.GetValue(assemblyNames); } } }