diff --git a/src/Gemstone/Common.cs b/src/Gemstone/Common.cs
index 14d3e14980..c080d0df9a 100644
--- a/src/Gemstone/Common.cs
+++ b/src/Gemstone/Common.cs
@@ -46,7 +46,6 @@
using System;
using System.Collections;
-using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
@@ -616,7 +615,10 @@ public static ulong GetTotalPhysicalMemory()
{
if (IsPosixEnvironment)
{
- string output = Command.Execute("awk", "'/MemTotal/ {print $2}' /proc/meminfo").StandardOutput;
+ // Pass the awk program as a single argument using double quotes (which the .NET argument tokenizer
+ // groups and strips); single quotes are shell-only syntax and, since the command is executed without
+ // a shell, would be passed to awk literally - causing "awk: unexpected character '''".
+ string output = Command.Execute("awk", "\"/MemTotal/ {print $2}\" /proc/meminfo").StandardOutput;
return ulong.Parse(output) * SI2.Kilo;
}
@@ -632,7 +634,9 @@ public static ulong GetAvailablePhysicalMemory()
{
if (IsPosixEnvironment)
{
- string output = Command.Execute("awk", "'/MemAvailable/ {print $2}' /proc/meminfo").StandardOutput;
+ // Double-quote the awk program so it is passed as a single argument; single quotes are shell-only
+ // syntax and would reach awk literally when executed without a shell (see GetTotalPhysicalMemory).
+ string output = Command.Execute("awk", "\"/MemAvailable/ {print $2}\" /proc/meminfo").StandardOutput;
return ulong.Parse(output) * SI2.Kilo;
}
diff --git a/src/Gemstone/Identity/UserInfoUnix.cs b/src/Gemstone/Identity/UserInfoUnix.cs
index 573e3bef6f..32807f207d 100644
--- a/src/Gemstone/Identity/UserInfoUnix.cs
+++ b/src/Gemstone/Identity/UserInfoUnix.cs
@@ -23,13 +23,8 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
-using System.Security;
-using System.Security.Principal;
using System.Text;
using Gemstone.Collections.CollectionExtensions;
using Gemstone.Console;
diff --git a/src/Gemstone/Identity/UserInfoWindows.cs b/src/Gemstone/Identity/UserInfoWindows.cs
index d105f31553..3660b3caea 100644
--- a/src/Gemstone/Identity/UserInfoWindows.cs
+++ b/src/Gemstone/Identity/UserInfoWindows.cs
@@ -25,7 +25,6 @@
using System.Collections;
using System.Collections.Generic;
using System.DirectoryServices;
-using System.Linq;
using System.Management;
using System.Reflection;
using System.Runtime.InteropServices;
diff --git a/src/Gemstone/Serialization.cs b/src/Gemstone/Serialization.cs
index 9b6a14adbe..1fd5978bed 100644
--- a/src/Gemstone/Serialization.cs
+++ b/src/Gemstone/Serialization.cs
@@ -73,29 +73,28 @@ private class LegacySerializationBinder : SerializationBinder
// Perform namespace transformations that occurred when migrating to the Grid Solutions Framework
// from various older versions of code with different namespaces
string newTypeName = typeName
- .Replace("TVA.", "Gemstone.")
- .Replace("GSF.TimeSeries.", "Gemstone.Timeseries.")
- .Replace("GSF.", "Gemstone.")
- .Replace("TimeSeriesFramework.", "Gemstone.Timeseries.")
+ .Replace(".TimeSeries.", ".Timeseries.") // Updated Gemstone casing for timeseries namespace
+ .Replace("GSF.Units.EE", "Gemstone.Numeric.EE") // Gemstone assembly relocation of EE namespace
+ .Replace("TVA.Units.EE", "Gemstone.Numeric.EE") // Gemstone assembly relocation of EE namespace
+ .Replace("TimeSeriesFramework.", "Gemstone.Timeseries.") // 2007 TVA Code Library "TimeSeriesFramework" namespace
.Replace("ConnectionTester.", "Gemstone.PhasorProtocols.") // PMU Connection Tester namespace
- .Replace("TVA.Phasors.", "Gemstone.PhasorProtocols.") // 2007 TVA Code Library namespace
- .Replace("Tva.Phasors.", "Gemstone.PhasorProtocols.") // 2008 TVA Code Library namespace
- .Replace("BpaPdcStream", "BPAPDCstream") // 2013 GSF uppercase phasor protocol namespace
- .Replace("FNet", "FNET") // 2013 GSF uppercase phasor protocol namespace
- .Replace("Iec61850_90_5", "IEC61850_90_5") // 2013 GSF uppercase phasor protocol namespace
- .Replace("Ieee1344", "IEEE1344") // 2013 GSF uppercase phasor protocol namespace
- .Replace("IeeeC37_118", "IEEEC37_118"); // 2013 GSF uppercase phasor protocol namespace
+ .Replace("TVA.Phasors.", "Gemstone.PhasorProtocols.") // 2007 TVA Code Library "Phasors" namespace
+ .Replace("Tva.Phasors.", "Gemstone.PhasorProtocols.") // 2008 TVA Code Library "Phasors" namespace
+ .Replace("GSF.", "Gemstone.") // 2013+ GSF root namespace
+ .Replace("TVA.", "Gemstone.") // 2007 TVA Code Library root namespace
+ .Replace("Tva.", "Gemstone.") // 2008 TVA Code Library root namespace
+ .Replace("BpaPdcStream", "BPAPDCstream") // 2013 updated GSF casing for phasor protocol namespace
+ .Replace("FNet", "FNET") // 2013 updated GSF casing for phasor protocol namespace
+ .Replace("Iec61850_90_5", "IEC61850_90_5") // 2013 updated GSF casing for phasor protocol namespace
+ .Replace("Ieee1344", "IEEE1344") // 2013 updated GSF casing for phasor protocol namespace
+ .Replace("IeeeC37_118", "IEEEC37_118"); // 2013 updated GSF casing for phasor protocol namespace
- // Check for 2009 TVA Code Library namespace
+ // Check for 2009 TVA Code Library "PhasorProtocols" namespace
if (newTypeName.StartsWith("PhasorProtocols", StringComparison.Ordinal))
newTypeName = "Gemstone." + newTypeName;
- // Check for 2014 LineFrequency type
- if (newTypeName.Equals("GSF.PhasorProtocols.LineFrequency", StringComparison.Ordinal))
- newTypeName = "Gemstone.Numeric.EE.LineFrequency";
-
- // Check for GSF LineFrequency type
- if (newTypeName.Equals("GSF.Units.EE.LineFrequency", StringComparison.Ordinal))
+ // Check for 2014 LineFrequency type (note: already replaced GSF with Gemstone here)
+ if (newTypeName.Equals("Gemstone.PhasorProtocols.LineFrequency", StringComparison.Ordinal))
newTypeName = "Gemstone.Numeric.EE.LineFrequency";
try
@@ -128,8 +127,45 @@ private class LegacySerializationBinder : SerializationBinder
// No type found; return null
return null;
}
+
+ ///
+ /// Controls the binding of a serialized object to a type name and assembly name during serialization.
+ ///
+ ///
+ /// Maps current Gemstone types back to their legacy GSF names so that XML written by Gemstone code
+ /// remains readable by .NET Framework consumers (PMU Connection Tester, older openPDC builds, etc.)
+ /// that only know the GSF-era types. The Gemstone-side reader translates these names back via
+ /// , so round-trip identity is preserved.
+ ///
+ /// The runtime type being serialized.
+ /// On return, the legacy assembly name to emit.
+ /// On return, the legacy fully-qualified type name to emit.
+ public override void BindToName(Type serializedType, out string? assemblyName, out string? typeName)
+ {
+ string fullName = serializedType.FullName ?? serializedType.Name;
+ string typeNamespace = serializedType.Namespace ?? string.Empty;
+ string runtimeAssembly = serializedType.Assembly.GetName().Name ?? string.Empty;
+
+ // Special case: Gemstone.Numeric.EE.* types (LineFrequency, PhasorType, etc.) historically
+ // lived in the GSF.Units.EE namespace inside the GSF.Core assembly.
+ if (typeNamespace == "Gemstone.Numeric.EE" || typeNamespace.StartsWith("Gemstone.Numeric.EE.", StringComparison.Ordinal))
+ {
+ typeName = fullName.Replace("Gemstone.Numeric.EE", "GSF.Units.EE", StringComparison.Ordinal);
+ assemblyName = "GSF.Core";
+ return;
+ }
+
+ // General case: Gemstone.* → GSF.* (and Timeseries → TimeSeries casing flip).
+ typeName = fullName
+ .Replace("Gemstone.Timeseries.", "GSF.TimeSeries.", StringComparison.Ordinal)
+ .Replace("Gemstone.", "GSF.", StringComparison.Ordinal);
+
+ assemblyName = runtimeAssembly
+ .Replace("Gemstone.Timeseries", "GSF.TimeSeries", StringComparison.Ordinal)
+ .Replace("Gemstone.", "GSF.", StringComparison.Ordinal);
+ }
}
-
+
///
/// Gets value for specified ; otherwise .
///
diff --git a/src/Gemstone/StringExtensions/FuzzyStrings/LongestCommonSubstring.cs b/src/Gemstone/StringExtensions/FuzzyStrings/LongestCommonSubstring.cs
index dd5bfc9c6e..dc16af2734 100644
--- a/src/Gemstone/StringExtensions/FuzzyStrings/LongestCommonSubstring.cs
+++ b/src/Gemstone/StringExtensions/FuzzyStrings/LongestCommonSubstring.cs
@@ -21,7 +21,6 @@
//
//******************************************************************************************************
-using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;
diff --git a/src/Gemstone/StringExtensions/StringExtensions.cs b/src/Gemstone/StringExtensions/StringExtensions.cs
index 3a4c2e1693..fb9fc8eb5d 100644
--- a/src/Gemstone/StringExtensions/StringExtensions.cs
+++ b/src/Gemstone/StringExtensions/StringExtensions.cs
@@ -250,15 +250,19 @@ public static T ConvertToType(this string? value, CultureInfo? culture)
///
public static object? ConvertToType(this string? value, Type type, CultureInfo? culture, bool suppressException = true)
{
- // Don't proceed further if string is empty.
+ // Handle the trivial string-to-string conversion
+ if (type == typeof(string))
+ return value;
+
+ // Don't proceed further if string is empty
if (string.IsNullOrEmpty(value))
return null;
- // Initialize return type if not specified.
+ // There is no way to guess what type the user intended to convert to
if (type is null)
throw new ArgumentNullException(nameof(type));
- // Initialize culture info if not specified.
+ // Initialize culture info if not specified
culture ??= CultureInfo.InvariantCulture;
// Handle array types as a special case