diff --git a/System.Resources.NetStandard/ResXDataNode.cs b/System.Resources.NetStandard/ResXDataNode.cs
index 1cb93d8..3398191 100644
--- a/System.Resources.NetStandard/ResXDataNode.cs
+++ b/System.Resources.NetStandard/ResXDataNode.cs
@@ -158,6 +158,11 @@ private void InitializeDataNode(string basePath)
}
}
}
+
+ if (nodeType != null && nodeType.Equals(typeof(ResXNullRef)))
+ {
+ value = new ResXNullRef();
+ }
}
///
@@ -619,11 +624,16 @@ public string GetValueTypeName(AssemblyName[] names)
///
public object GetValue(ITypeResolutionService typeResolver)
{
+ if (value is ResXNullRef)
+ {
+ return null;
+ }
+
if (value != null)
{
return value;
}
-
+
object result = null;
if (FileRefFullPath != null)
{
@@ -962,6 +972,13 @@ public Type GetType(string name, bool throwOnError, bool ignoreCase)
result = typeof(ResXFileRef);
return result;
}
+
+ // Replace the WinForms ResXNullRef with the copy in this library
+ if (name.StartsWith(ResXConstants.ResXNullRef_TypeNameAndAssembly, StringComparison.Ordinal))
+ {
+ result = typeof(ResXNullRef);
+ return result;
+ }
// Missed in cache, try to resolve the type from the reference assemblies.
if (name.IndexOf(',') != -1)
diff --git a/System.Resources.NetStandard/ResxConstants.cs b/System.Resources.NetStandard/ResxConstants.cs
index 6274ed7..73720dd 100644
--- a/System.Resources.NetStandard/ResxConstants.cs
+++ b/System.Resources.NetStandard/ResxConstants.cs
@@ -10,5 +10,8 @@ internal class ResXConstants
public const string ResxFileRefTypeInfo = "System.Resources.ResXFileRef, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
public const string ResxFileRef_TypeNameAndAssembly = "System.Resources.ResXFileRef, System.Windows.Forms";
+
+ public const string ResxNullRefTypeInfo = "System.Resources.ResXNullRef, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
+ public const string ResXNullRef_TypeNameAndAssembly = "System.Resources.ResXNullRef, System.Windows.Forms";
}
}
\ No newline at end of file
diff --git a/System.Resources.NetStandard/WinformsTypeMappers.cs b/System.Resources.NetStandard/WinformsTypeMappers.cs
index 235a94e..b30380c 100644
--- a/System.Resources.NetStandard/WinformsTypeMappers.cs
+++ b/System.Resources.NetStandard/WinformsTypeMappers.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace System.Resources.NetStandard
+namespace System.Resources.NetStandard
{
internal static class WinformsTypeMappers
{
@@ -12,13 +8,14 @@ public static Func InterceptWinformsTypes(Func typeNa
{
if (type.AssemblyQualifiedName == typeof(ResXFileRef).AssemblyQualifiedName)
{
- return NetStandard.ResXConstants.ResxFileRefTypeInfo;
+ return ResXConstants.ResxFileRefTypeInfo;
}
- else
+ else if (type.AssemblyQualifiedName == typeof(ResXNullRef).AssemblyQualifiedName)
{
- if (typeNameConverter != null) return typeNameConverter(type);
- else return null;
+ return ResXConstants.ResxNullRefTypeInfo;
}
+ else if (typeNameConverter != null) return typeNameConverter(type);
+ else return null;
};
}
diff --git a/Tests/Example.Designer.cs b/Tests/Example.Designer.cs
index 3222955..3f12d7b 100644
--- a/Tests/Example.Designer.cs
+++ b/Tests/Example.Designer.cs
@@ -1,123 +1,142 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-namespace System.Resources.Tests {
- using System;
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Example {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Example() {
- }
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Resources.Tests.Example", typeof(Example).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- ///
- /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
- ///
- internal static System.Drawing.Icon Error {
- get {
- object obj = ResourceManager.GetObject("Error", resourceCulture);
- return ((System.Drawing.Icon)(obj));
- }
- }
-
- ///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
- ///
- internal static System.Drawing.Bitmap ErrorControl {
- get {
- object obj = ResourceManager.GetObject("ErrorControl", resourceCulture);
- return ((System.Drawing.Bitmap)(obj));
- }
- }
-
- ///
- /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?>
- ///<Root>
- /// <Element>Text</Element>
- ///</Root>.
- ///
- internal static string FileRef {
- get {
- return ResourceManager.GetString("FileRef", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
- ///<root>
- /// <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
- /// <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
- /// <xsd:element name="root" msdata:IsDataSet="true">
- /// <xsd:complexType>
- /// <xsd:choice maxOccurs="unbounded">
- /// <xsd:element name="metadata">
- /// <xsd:complexType>
- /// <xsd:sequence>
- /// <xsd:element name="va [rest of string was truncated]";.
- ///
- internal static string ResxWithFileRef {
- get {
- return ResourceManager.GetString("ResxWithFileRef", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Text.
- ///
- internal static string text_ansi {
- get {
- return ResourceManager.GetString("text_ansi", resourceCulture);
- }
- }
- }
-}
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace System.Resources.Tests {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Example {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Example() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Resources.Tests.Example", typeof(Example).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
+ ///
+ internal static System.Drawing.Icon Error {
+ get {
+ object obj = ResourceManager.GetObject("Error", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ErrorControl {
+ get {
+ object obj = ResourceManager.GetObject("ErrorControl", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?>
+ ///<Root>
+ /// <Element>Text</Element>
+ ///</Root>.
+ ///
+ internal static string FileRef {
+ get {
+ return ResourceManager.GetString("FileRef", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
+ ///<root>
+ /// <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ /// <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ /// <xsd:element name="root" msdata:IsDataSet="true">
+ /// <xsd:complexType>
+ /// <xsd:choice maxOccurs="unbounded">
+ /// <xsd:element name="metadata">
+ /// <xsd:complexType>
+ /// <xsd:sequence>
+ /// <xsd:element name="va [rest of string was truncated]";.
+ ///
+ internal static string ResxWithFileRef {
+ get {
+ return ResourceManager.GetString("ResxWithFileRef", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
+ ///<root>
+ /// <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ /// <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ /// <xsd:element name="root" msdata:IsDataSet="true">
+ /// <xsd:complexType>
+ /// <xsd:choice maxOccurs="unbounded">
+ /// <xsd:element name="metadata">
+ /// <xsd:complexType>
+ /// <xsd:sequence>
+ /// <xsd:element name="va [rest of string was truncated]";.
+ ///
+ internal static string ResxWithNullRef {
+ get {
+ return ResourceManager.GetString("ResxWithNullRef", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Text.
+ ///
+ internal static string text_ansi {
+ get {
+ return ResourceManager.GetString("text_ansi", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/Tests/Example.resx b/Tests/Example.resx
index e74bc50..0d40358 100644
--- a/Tests/Example.resx
+++ b/Tests/Example.resx
@@ -1,136 +1,139 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
- TestResources\Files\Error.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- TestResources\Files\ErrorControl.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- TestResources\Files\FileRef.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
-
-
- ResxWithFileRef.resx;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
-
-
- TestResources\Files\text.ansi.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ TestResources\Files\Error.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ TestResources\Files\ErrorControl.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ TestResources\Files\FileRef.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
+
+ ResxWithFileRef.resx;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
+
+ TestResources\Files\text.ansi.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
+
+
+ ResxWithNullRef.resx;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
\ No newline at end of file
diff --git a/Tests/ResxDataNodeTests.cs b/Tests/ResxDataNodeTests.cs
index 1e0beac..634239c 100644
--- a/Tests/ResxDataNodeTests.cs
+++ b/Tests/ResxDataNodeTests.cs
@@ -6,13 +6,10 @@
using System.Collections;
using System.Drawing;
using System.Reflection;
-using System.Reflection.PortableExecutable;
using System.Resources.Tests;
using Xunit;
using System.IO;
-using System.Linq;
using System.Text;
-using System.ComponentModel.Design;
namespace System.Resources.NetStandard.Tests
{
@@ -105,7 +102,7 @@ private List ReaderToNodes(ResXResourceReader reader)
}
[Fact]
- public void ResxDataNode_ResXFileRefsWrittenBackWithSameAssemblyInfo()
+ public void ResxDataNode_ResXFileRefs_WrittenBackWithSameAssemblyInfo()
{
// This test ensures compatibility with tooling like Visual Studio's visual ResX editor
@@ -157,5 +154,93 @@ string customTypeConverter(Type type)
Assert.Equal(expected, actual);
}
+
+ [Fact]
+ public void ResxDataNode_CreateForResXNullRef()
+ {
+ // Simulate an XML file stored in resources, which uses a ResXNullRef. The actual resx XML looks like:
+ /*
+
+
+
+
+ */
+
+ var nodeInfo = new DataNodeInfo
+ {
+ Name = "Test",
+ ReaderPosition = new Point(1, 2),
+ TypeName = "System.Resources.ResXNullRef, System.Windows.Forms",
+ ValueData = "",
+ };
+ var dataNode = new ResXDataNode(nodeInfo, null);
+ var typeResolver = new AssemblyNamesTypeResolutionService(Array.Empty());
+ Assert.Equal("Test", dataNode.Name);
+ Assert.Null(dataNode.GetValue(typeResolver));
+
+ StringBuilder resxOutput = new StringBuilder();
+ using (ResXResourceWriter resx = new ResXResourceWriter(new StringWriter(resxOutput)))
+ {
+ resx.AddResource(dataNode);
+ }
+
+ Assert.Contains("", resxOutput.ToString());
+ }
+
+ [Fact]
+ public void ResxDataNode_ResXNullRef_RoundTrip()
+ {
+ object referencedFileContent = null;
+ var nodeInfo = new DataNodeInfo
+ {
+ Name = "ResxWithNullRef",
+ ReaderPosition = new Point(1, 2),
+ TypeName = "System.Resources.ResXNullRef, System.Windows.Forms",
+ ValueData = ""
+ };
+ var dataNode = new ResXDataNode(nodeInfo, null);
+
+ StringBuilder resxOutput = new StringBuilder();
+ using (ResXResourceWriter writer = new ResXResourceWriter(new StringWriter(resxOutput)))
+ {
+ writer.AddResource(dataNode);
+ }
+ using (ResXResourceReader reader = new ResXResourceReader(new StringReader(resxOutput.ToString())))
+ {
+ var dictionary = new Dictionary