2
0
Эх сурвалжийг харах

Fixes #4231. NativeAot project throws when running the published executable (#4232)

* Fixes #4231. NativeAot project throws when running the published executable

* Code cleanup

---------

Co-authored-by: Tig <[email protected]>
BDisp 1 өдөр өмнө
parent
commit
da9286d3f4

+ 2 - 2
Examples/NativeAot/Publish_linux-x64_Debug.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
 
-dotnet clean
-dotnet build
+dotnet clean -c Debug
+dotnet build -c Debug
 dotnet publish -c Debug -r linux-x64 --self-contained

+ 2 - 2
Examples/NativeAot/Publish_linux-x64_Release.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
 
-dotnet clean
-dotnet build
+dotnet clean -c Release
+dotnet build -c Release
 dotnet publish -c Release -r linux-x64 --self-contained

+ 2 - 2
Examples/NativeAot/Publish_osx-x64_Debug.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
 
-dotnet clean
-dotnet build
+dotnet clean -c Debug
+dotnet build -c Debug
 dotnet publish -c Debug -r osx-x64 --self-contained

+ 2 - 2
Examples/NativeAot/Publish_osx-x64_Release.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
 
-dotnet clean
-dotnet build
+dotnet clean -c Release
+dotnet build -c Release
 dotnet publish -c Release -r osx-x64 --self-contained

+ 27 - 5
Terminal.Gui/Configuration/DeepCloner.cs

@@ -278,17 +278,37 @@ public static class DeepCloner
 
         // Determine dictionary type and comparer
         Type [] genericArgs = type.GetGenericArguments ();
-        Type dictType = genericArgs.Length == 2
-            ? typeof (Dictionary<,>).MakeGenericType (genericArgs)
-            : typeof (Dictionary<object, object>);
+        Type dictType;
+
+        if (genericArgs.Length == 2)
+        {
+            if (type.GetGenericTypeDefinition () == typeof (Dictionary<,>))
+            {
+                dictType = typeof (Dictionary<,>).MakeGenericType (genericArgs);
+            }
+            else if (type.GetGenericTypeDefinition () == typeof (ConcurrentDictionary<,>))
+            {
+                dictType = typeof (ConcurrentDictionary<,>).MakeGenericType (genericArgs);
+            }
+            else
+            {
+                throw new InvalidOperationException (
+                                                     $"Unsupported dictionary type: {type}. Only Dictionary<,> and ConcurrentDictionary<,> are supported.");
+            }
+        }
+        else
+        {
+            dictType = typeof (Dictionary<object, object>);
+        }
+
         object? comparer = type.GetProperty ("Comparer")?.GetValue (source);
 
         // Create a temporary dictionary to hold cloned key-value pairs
         IDictionary tempDict = CreateDictionaryInstance (dictType, comparer);
         visited.TryAdd (source, tempDict);
 
-
         object? lastKey = null;
+
         try
         {
             // Clone all key-value pairs
@@ -311,7 +331,9 @@ public static class DeepCloner
         catch (InvalidOperationException ex)
         {
             // Handle cases where the dictionary is modified during enumeration
-            throw new InvalidOperationException ($"Error cloning dictionary ({source}) (last key was \"{lastKey}\"). Ensure the source dictionary is not modified during cloning.", ex);
+            throw new InvalidOperationException (
+                                                 $"Error cloning dictionary ({source}) (last key was \"{lastKey}\"). Ensure the source dictionary is not modified during cloning.",
+                                                 ex);
         }
 
         // If the original dictionary type has a parameterless constructor, create a new instance

+ 87 - 0
Tests/UnitTestsParallelizable/Configuration/DeepClonerTests.cs

@@ -551,4 +551,91 @@ public class DeepClonerTests
         Assert.True (stopwatch.ElapsedMilliseconds < 1000); // Ensure it completes within 1 second
     }
 
+    [Fact]
+    public void CloneDictionary_ShouldClone_NormalDictionary ()
+    {
+        // Arrange: A supported generic dictionary
+        var original = new Dictionary<string, int>
+        {
+            ["one"] = 1,
+            ["two"] = 2,
+            ["three"] = 3
+        };
+
+        // Act
+        var cloned = DeepCloner.DeepClone (original);
+
+        // Assert
+        Assert.NotNull (cloned);
+        Assert.NotSame (original, cloned); // must be a new instance
+        Assert.Equal (original, cloned);   // must have same contents
+        Assert.Equal (original.Count, cloned.Count);
+        Assert.Equal (original ["one"], cloned ["one"]);
+        Assert.Equal (original ["two"], cloned ["two"]);
+        Assert.Equal (original ["three"], cloned ["three"]);
+    }
+
+    [Fact]
+    public void CloneDictionary_ShouldClone_ConcurrentDictionary ()
+    {
+        // Arrange
+        var original = new ConcurrentDictionary<string, string>
+        {
+            ["a"] = "alpha",
+            ["b"] = "beta"
+        };
+
+        // Act
+        var cloned = DeepCloner.DeepClone (original);
+
+        // Assert
+        Assert.NotSame (original, cloned);
+        Assert.Equal (original, cloned);
+    }
+
+    [Fact]
+    public void CloneDictionary_Empty_Dictionary_ShouldWork ()
+    {
+        // Arrange
+        var original = new Dictionary<int, string> ();
+
+        // Act
+        var cloned = DeepCloner.DeepClone (original);
+
+        // Assert
+        Assert.NotSame (original, cloned);
+        Assert.Empty (cloned!);
+    }
+
+    [Fact]
+    public void CloneDictionary_Empty_ConcurrentDictionary_ShouldWork ()
+    {
+        // Arrange
+        var original = new ConcurrentDictionary<int, string> ();
+
+        // Act
+        var cloned = DeepCloner.DeepClone (original);
+
+        // Assert
+        Assert.NotSame (original, cloned);
+        Assert.Empty (cloned!);
+    }
+
+    [Fact]
+    public void CloneDictionary_With_Unsupported_Dictionary_Throws ()
+    {
+        // Arrange: A generic dictionary type (SortedDictionary for example)
+        var unsupportedDict = new SortedDictionary<int, string>
+        {
+            { 1, "A" },
+            { 2, "B" }
+        };
+
+        // Act & Assert: DeepCloner should throw
+        Assert.ThrowsAny<InvalidOperationException> (() =>
+                                                     {
+                                                         // This should throw, because DeepCloner does not support SortedDictionary
+                                                         _ = DeepCloner.DeepClone (unsupportedDict);
+                                                     });
+    }
 }

BIN
local_packages/Terminal.Gui.2.0.0.nupkg


BIN
local_packages/Terminal.Gui.2.0.0.snupkg