Skip to content

Commit

Permalink
Use ResXFileRef from this project. Fixes #5
Browse files Browse the repository at this point in the history
Test we can read file refs that we write.

Also move type data string to ResXConstants

Demonstate writing winforms assembly for internal ResXFileRef

Move winforms type conversion to library internals

Test user-provided type converters don't break winforms overwrites

Fix NullReferenceException on non-Windows platforms.

Use an ordinal comparison for type names.

Fix tests.

Switch back to C# 7.3.

Use a StringWriter instead of a temp file.

Remove local fix for tests that breaks the build.
  • Loading branch information
bgrainger authored and farlee2121 committed Dec 3, 2023
1 parent 84243d1 commit f5caaa9
Show file tree
Hide file tree
Showing 11 changed files with 541 additions and 11 deletions.
21 changes: 14 additions & 7 deletions System.Resources.NetStandard/ResXDataNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ public sealed class ResXDataNode : ISerializable
// No public property to force using constructors for the following reasons:
// 1. one of the constructors needs this field (if used) to initialize the object, make it consistent with the other ctrs to avoid errors.
// 2. once the object is constructed the delegate should not be changed to avoid getting inconsistent results.
private Func<Type, string> typeNameConverter;
private Func<Type, string> typeNameConverter = WinformsTypeMappers.InterceptWinformsTypes(null);

private ResXDataNode()
{
}

internal ResXDataNode DeepClone()
public ResXDataNode DeepClone()
{
return new ResXDataNode
{
Expand Down Expand Up @@ -87,7 +87,7 @@ public ResXDataNode(string name, object value, Func<Type, string> typeNameConver
throw (new ArgumentException(nameof(name)));
}

this.typeNameConverter = typeNameConverter;
this.typeNameConverter = WinformsTypeMappers.InterceptWinformsTypes(typeNameConverter);

Type valueType = (value == null) ? typeof(object) : value.GetType();
if (value != null && !valueType.IsSerializable)
Expand Down Expand Up @@ -116,7 +116,7 @@ public ResXDataNode(string name, ResXFileRef fileRef, Func<Type, string> typeNam

this.name = name;
this.fileRef = fileRef ?? throw new ArgumentNullException(nameof(fileRef));
this.typeNameConverter = typeNameConverter;
this.typeNameConverter = WinformsTypeMappers.InterceptWinformsTypes(typeNameConverter);
}

internal ResXDataNode(DataNodeInfo nodeInfo, string basePath)
Expand Down Expand Up @@ -864,8 +864,8 @@ internal class AssemblyNamesTypeResolutionService : ITypeResolutionService
private Hashtable cachedAssemblies;
private Hashtable cachedTypes;

private static readonly string s_dotNetPath = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"), "dotnet\\shared");
private static readonly string s_dotNetPathX86 = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "dotnet\\shared");
private static readonly string s_dotNetPath = Environment.GetEnvironmentVariable("ProgramFiles") != null ? Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"), "dotnet", "shared") : null;
private static readonly string s_dotNetPathX86 = Environment.GetEnvironmentVariable("ProgramFiles(x86)") != null ? Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "dotnet", "shared") : null;

internal AssemblyNamesTypeResolutionService(AssemblyName[] names)
{
Expand Down Expand Up @@ -956,6 +956,13 @@ public Type GetType(string name, bool throwOnError, bool ignoreCase)
return result;
}

// Replace the WinForms ResXFileRef with the copy in this library
if (name.StartsWith(ResXConstants.ResxFileRef_TypeNameAndAssembly, StringComparison.Ordinal))
{
result = typeof(ResXFileRef);
return result;
}

// Missed in cache, try to resolve the type from the reference assemblies.
if (name.IndexOf(',') != -1)
{
Expand Down Expand Up @@ -1047,7 +1054,7 @@ public Type GetType(string name, bool throwOnError, bool ignoreCase)
/// </summary>
private bool IsDotNetAssembly(string assemblyPath)
{
return assemblyPath != null && (assemblyPath.StartsWith(s_dotNetPath, StringComparison.OrdinalIgnoreCase) || assemblyPath.StartsWith(s_dotNetPathX86, StringComparison.OrdinalIgnoreCase));
return assemblyPath != null && s_dotNetPath != null && (assemblyPath.StartsWith(s_dotNetPath, StringComparison.OrdinalIgnoreCase) || assemblyPath.StartsWith(s_dotNetPathX86, StringComparison.OrdinalIgnoreCase));
}

public void ReferenceAssembly(AssemblyName name)
Expand Down
8 changes: 4 additions & 4 deletions System.Resources.NetStandard/ResXResourceWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public class ResXResourceWriter : IResourceWriter
bool hasBeenSaved;
bool initialized;

private readonly Func<Type, string> typeNameConverter; // no public property to be consistent with ResXDataNode class.
private readonly Func<Type, string> typeNameConverter = WinformsTypeMappers.InterceptWinformsTypes(null); // no public property to be consistent with ResXDataNode class.

/// <summary>
/// Base Path for ResXFileRefs.
Expand All @@ -119,7 +119,7 @@ public ResXResourceWriter(string fileName)
public ResXResourceWriter(string fileName, Func<Type, string> typeNameConverter)
{
this.fileName = fileName;
this.typeNameConverter = typeNameConverter;
this.typeNameConverter = WinformsTypeMappers.InterceptWinformsTypes(typeNameConverter);
}

/// <summary>
Expand All @@ -132,7 +132,7 @@ public ResXResourceWriter(Stream stream)
public ResXResourceWriter(Stream stream, Func<Type, string> typeNameConverter)
{
this.stream = stream;
this.typeNameConverter = typeNameConverter;
this.typeNameConverter = WinformsTypeMappers.InterceptWinformsTypes(typeNameConverter);
}

/// <summary>
Expand All @@ -145,7 +145,7 @@ public ResXResourceWriter(TextWriter textWriter)
public ResXResourceWriter(TextWriter textWriter, Func<Type, string> typeNameConverter)
{
this.textWriter = textWriter;
this.typeNameConverter = typeNameConverter;
this.typeNameConverter = WinformsTypeMappers.InterceptWinformsTypes(typeNameConverter);
}

~ResXResourceWriter()
Expand Down
4 changes: 4 additions & 0 deletions System.Resources.NetStandard/ResxConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@ internal class ResXConstants

public static string ResHeaderReaderTypeName => ResHeaderReader.Split(',')[0].Trim();
public static string ResHeaderWriterTypeName => ResHeaderWriter.Split(',')[0].Trim();


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";
}
}
26 changes: 26 additions & 0 deletions System.Resources.NetStandard/WinformsTypeMappers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace System.Resources.NetStandard
{
internal static class WinformsTypeMappers
{
public static Func<Type, string> InterceptWinformsTypes(Func<Type,string> typeNameConverter)
{
return (Type type) =>
{
if (type.AssemblyQualifiedName == typeof(ResXFileRef).AssemblyQualifiedName)
{
return NetStandard.ResXConstants.ResxFileRefTypeInfo;
}
else
{
if (typeNameConverter != null) return typeNameConverter(type);
else return null;
}
};
}

}
}
123 changes: 123 additions & 0 deletions Tests/Example.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f5caaa9

Please sign in to comment.