Skip to content

Commit 97e1a24

Browse files
Merge pull request #1203 from microsoft/is/copy-ctrs
Fix Deep copying of objects implementing the dictionary type using copy constructors
2 parents 11320f0 + 1a9e58c commit 97e1a24

18 files changed

+92
-28
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
7+
namespace Microsoft.OpenApi.Helpers
8+
{
9+
/// <summary>
10+
/// Helper class for deep cloning dictionaries.
11+
/// </summary>
12+
internal class DictionaryCloneHelper
13+
{
14+
/// <summary>
15+
/// Deep clone key value pairs in a dictionary.
16+
/// </summary>
17+
/// <typeparam name="T">The type of the key of the dictionary.</typeparam>
18+
/// <typeparam name="U">The type of the value of the dictionary.</typeparam>
19+
/// <param name="dictionary">The target dictionary to clone.</param>
20+
/// <returns>The cloned dictionary.</returns>
21+
internal static Dictionary<T, U> Clone<T, U>(IDictionary<T, U> dictionary)
22+
{
23+
if (dictionary is null) return null;
24+
var clonedDictionary = new Dictionary<T, U>(dictionary.Keys.Count);
25+
26+
foreach (var kvp in dictionary)
27+
{
28+
// Create instance of the specified type using the constructor matching the specified parameter types.
29+
clonedDictionary[kvp.Key] = (U)Activator.CreateInstance(kvp.Value.GetType(), kvp.Value);
30+
}
31+
32+
33+
return clonedDictionary;
34+
}
35+
}
36+
}

src/Microsoft.OpenApi/Models/OpenApiCallback.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using Microsoft.OpenApi.Any;
66
using Microsoft.OpenApi.Expressions;
7+
using Microsoft.OpenApi.Helpers;
78
using Microsoft.OpenApi.Interfaces;
89
using Microsoft.OpenApi.Writers;
910

src/Microsoft.OpenApi/Models/OpenApiComponents.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
using System;
54
using System.Collections.Generic;
65
using System.Linq;
7-
using Microsoft.OpenApi.Any;
6+
using Microsoft.OpenApi.Helpers;
87
using Microsoft.OpenApi.Interfaces;
98
using Microsoft.OpenApi.Writers;
109

@@ -78,15 +77,15 @@ public OpenApiComponents() { }
7877
/// </summary>
7978
public OpenApiComponents(OpenApiComponents components)
8079
{
81-
Schemas = components?.Schemas != null ? new Dictionary<string, OpenApiSchema>(components.Schemas) : null;
82-
Responses = components?.Responses != null ? new Dictionary<string, OpenApiResponse>(components.Responses) : null;
83-
Parameters = components?.Parameters != null ? new Dictionary<string, OpenApiParameter>(components.Parameters) : null;
84-
Examples = components?.Examples != null ? new Dictionary<string, OpenApiExample>(components.Examples) : null;
85-
RequestBodies = components?.RequestBodies != null ? new Dictionary<string, OpenApiRequestBody>(components.RequestBodies) : null;
86-
Headers = components?.Headers != null ? new Dictionary<string, OpenApiHeader>(components.Headers) : null;
87-
SecuritySchemes = components?.SecuritySchemes != null ? new Dictionary<string, OpenApiSecurityScheme>(components.SecuritySchemes) : null;
88-
Links = components?.Links != null ? new Dictionary<string, OpenApiLink>(components.Links) : null;
89-
Callbacks = components?.Callbacks != null ? new Dictionary<string, OpenApiCallback>(components.Callbacks) : null;
80+
Schemas = DictionaryCloneHelper.Clone(components?.Schemas);
81+
Responses = DictionaryCloneHelper.Clone(components?.Responses);
82+
Parameters = DictionaryCloneHelper.Clone(components?.Parameters);
83+
Examples = DictionaryCloneHelper.Clone(components?.Examples);
84+
RequestBodies = DictionaryCloneHelper.Clone(components?.RequestBodies);
85+
Headers = DictionaryCloneHelper.Clone(components?.Headers);
86+
SecuritySchemes = DictionaryCloneHelper.Clone(components?.SecuritySchemes);
87+
Links = DictionaryCloneHelper.Clone(components?.Links);
88+
Callbacks = DictionaryCloneHelper.Clone(components?.Callbacks);
9089
Extensions = components?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(components.Extensions) : null;
9190
}
9291

src/Microsoft.OpenApi/Models/OpenApiDocument.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Security.Cryptography;
99
using System.Text;
1010
using Microsoft.OpenApi.Exceptions;
11+
using Microsoft.OpenApi.Helpers;
1112
using Microsoft.OpenApi.Interfaces;
1213
using Microsoft.OpenApi.Services;
1314
using Microsoft.OpenApi.Writers;

src/Microsoft.OpenApi/Models/OpenApiEncoding.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using Microsoft.OpenApi.Any;
66
using Microsoft.OpenApi.Extensions;
7+
using Microsoft.OpenApi.Helpers;
78
using Microsoft.OpenApi.Interfaces;
89
using Microsoft.OpenApi.Writers;
910

@@ -64,7 +65,7 @@ public OpenApiEncoding() {}
6465
public OpenApiEncoding(OpenApiEncoding encoding)
6566
{
6667
ContentType = encoding?.ContentType ?? ContentType;
67-
Headers = encoding?.Headers != null ? new Dictionary<string, OpenApiHeader>(encoding.Headers) : null;
68+
Headers = DictionaryCloneHelper.Clone(encoding?.Headers);
6869
Style = encoding?.Style ?? Style;
6970
Explode = encoding?.Explode ?? Explode;
7071
AllowReserved = encoding?.AllowReserved ?? AllowReserved;

src/Microsoft.OpenApi/Models/OpenApiExample.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using Microsoft.OpenApi.Any;
6+
using Microsoft.OpenApi.Helpers;
67
using Microsoft.OpenApi.Interfaces;
78
using Microsoft.OpenApi.Writers;
89

src/Microsoft.OpenApi/Models/OpenApiHeader.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using Microsoft.OpenApi.Any;
66
using Microsoft.OpenApi.Extensions;
7+
using Microsoft.OpenApi.Helpers;
78
using Microsoft.OpenApi.Interfaces;
89
using Microsoft.OpenApi.Writers;
910

@@ -107,8 +108,8 @@ public OpenApiHeader(OpenApiHeader header)
107108
AllowReserved = header?.AllowReserved ?? AllowReserved;
108109
Schema = header?.Schema != null ? new(header?.Schema) : null;
109110
Example = OpenApiAnyCloneHelper.CloneFromCopyConstructor(header?.Example);
110-
Examples = header?.Examples != null ? new Dictionary<string, OpenApiExample>(header.Examples) : null;
111-
Content = header?.Content != null ? new Dictionary<string, OpenApiMediaType>(header.Content) : null;
111+
Examples = DictionaryCloneHelper.Clone(header?.Examples);
112+
Content = DictionaryCloneHelper.Clone(header?.Content);
112113
Extensions = header?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(header.Extensions) : null;
113114
}
114115

src/Microsoft.OpenApi/Models/OpenApiMediaType.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using Microsoft.OpenApi.Any;
6+
using Microsoft.OpenApi.Helpers;
67
using Microsoft.OpenApi.Interfaces;
78
using Microsoft.OpenApi.Writers;
89

@@ -55,8 +56,8 @@ public OpenApiMediaType(OpenApiMediaType mediaType)
5556
{
5657
Schema = mediaType?.Schema != null ? new(mediaType?.Schema) : null;
5758
Example = OpenApiAnyCloneHelper.CloneFromCopyConstructor(mediaType?.Example);
58-
Examples = mediaType?.Examples != null ? new Dictionary<string, OpenApiExample>(mediaType.Examples) : null;
59-
Encoding = mediaType?.Encoding != null ? new Dictionary<string, OpenApiEncoding>(mediaType.Encoding) : null;
59+
Examples = DictionaryCloneHelper.Clone(mediaType?.Examples);
60+
Encoding = DictionaryCloneHelper.Clone(mediaType?.Encoding);
6061
Extensions = mediaType?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(mediaType.Extensions) : null;
6162
}
6263

src/Microsoft.OpenApi/Models/OpenApiOperation.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using Microsoft.OpenApi.Any;
8+
using Microsoft.OpenApi.Helpers;
89
using Microsoft.OpenApi.Interfaces;
910
using Microsoft.OpenApi.Writers;
1011

@@ -124,7 +125,7 @@ public OpenApiOperation(OpenApiOperation operation)
124125
Parameters = operation?.Parameters != null ? new List<OpenApiParameter>(operation.Parameters) : null;
125126
RequestBody = operation?.RequestBody != null ? new(operation?.RequestBody) : null;
126127
Responses = operation?.Responses != null ? new(operation?.Responses) : null;
127-
Callbacks = operation?.Callbacks != null ? new Dictionary<string, OpenApiCallback>(operation.Callbacks) : null;
128+
Callbacks = DictionaryCloneHelper.Clone(operation?.Callbacks);
128129
Deprecated = operation?.Deprecated ?? Deprecated;
129130
Security = operation?.Security != null ? new List<OpenApiSecurityRequirement>(operation.Security) : null;
130131
Servers = operation?.Servers != null ? new List<OpenApiServer>(operation.Servers) : null;

src/Microsoft.OpenApi/Models/OpenApiParameter.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Runtime;
77
using Microsoft.OpenApi.Any;
88
using Microsoft.OpenApi.Extensions;
9+
using Microsoft.OpenApi.Helpers;
910
using Microsoft.OpenApi.Interfaces;
1011
using Microsoft.OpenApi.Writers;
1112

@@ -162,9 +163,9 @@ public OpenApiParameter(OpenApiParameter parameter)
162163
Explode = parameter?.Explode ?? Explode;
163164
AllowReserved = parameter?.AllowReserved ?? AllowReserved;
164165
Schema = parameter?.Schema != null ? new(parameter?.Schema) : null;
165-
Examples = parameter?.Examples != null ? new Dictionary<string, OpenApiExample>(parameter.Examples) : null;
166+
Examples = DictionaryCloneHelper.Clone(parameter?.Examples);
166167
Example = OpenApiAnyCloneHelper.CloneFromCopyConstructor(parameter?.Example);
167-
Content = parameter?.Content != null ? new Dictionary<string, OpenApiMediaType>(parameter.Content) : null;
168+
Content = DictionaryCloneHelper.Clone(parameter?.Content);
168169
Extensions = parameter?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(parameter.Extensions) : null;
169170
AllowEmptyValue = parameter?.AllowEmptyValue ?? AllowEmptyValue;
170171
Deprecated = parameter?.Deprecated ?? Deprecated;

0 commit comments

Comments
 (0)