Skip to content

Commit f3e6d94

Browse files
author
Prashanth Govindarajan
committed
First cut of deprecating BF usage
1 parent 629ad50 commit f3e6d94

10 files changed

+119
-13
lines changed

src/libraries/System.Configuration.ConfigurationManager/ref/System.Configuration.ConfigurationManager.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,7 @@ public enum SettingsSerializeAs
12131213
{
12141214
String = 0,
12151215
Xml = 1,
1216+
[System.ObsoleteAttribute(System.Obsoletions.BinaryFormatterMessage + @". Consider using Xml instead.", false)]
12161217
Binary = 2,
12171218
ProviderSpecific = 3,
12181219
}

src/libraries/System.Configuration.ConfigurationManager/ref/System.Configuration.ConfigurationManager.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
</PropertyGroup>
1010
<ItemGroup>
1111
<Compile Include="System.Configuration.ConfigurationManager.cs" />
12+
<Compile Include="$(CommonPath)System\Obsoletions.cs" Link="Common\System\Obsoletions.cs" />
1213
</ItemGroup>
1314
<ItemGroup>
1415
<ProjectReference Include="..\..\System.Security.Permissions\ref\System.Security.Permissions.csproj" />

src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@
248248
<Compile Include="System\UriIdnScope.cs" />
249249
<Compile Include="$(CommonPath)System\IO\TempFileCollection.cs"
250250
Link="Common\System\IO\TempFileCollection.cs" />
251+
<Compile Include="$(CommonPath)System\Obsoletions.cs" Link="Common\System\Obsoletions.cs" />
251252
</ItemGroup>
252253
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
253254
<ProjectReference Include="$(LibrariesProjectRoot)System.Security.Cryptography.ProtectedData\src\System.Security.Cryptography.ProtectedData.csproj" />

src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/LocalFileSettingsProvider.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,9 @@ private XmlNode SerializeToXmlElement(SettingsProperty setting, SettingsProperty
462462

463463
string serializedValue = value.SerializedValue as string;
464464

465+
#pragma warning disable CS0618 // Type or member is obsolete
465466
if (serializedValue == null && setting.SerializeAs == SettingsSerializeAs.Binary)
467+
#pragma warning restore CS0618 // Type or member is obsolete
466468
{
467469
// SettingsPropertyValue returns a byte[] in the binary serialization case. We need to
468470
// encode this - we use base64 since SettingsPropertyValue understands it and we won't have

src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/SettingsProperty.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ namespace System.Configuration
55
{
66
public class SettingsProperty
77
{
8+
internal static bool EnableUnsafeBinaryFormatterInPropertyValueSerialization { get; } = AppContext.TryGetSwitch("System.Configuration.ConfigurationManager.EnableUnsafeBinaryFormatterInPropertyValueSerialization", out bool isEnabled) ? isEnabled : false;
9+
810
public virtual string Name { get; set; }
911
public virtual bool IsReadOnly { get; set; }
1012
public virtual object DefaultValue { get; set; }
@@ -37,7 +39,19 @@ public SettingsProperty(
3739
Provider = provider;
3840
IsReadOnly = isReadOnly;
3941
DefaultValue = defaultValue;
40-
SerializeAs = serializeAs;
42+
#pragma warning disable CS0618 // Type or member is obsolete
43+
if (serializeAs == SettingsSerializeAs.Binary)
44+
#pragma warning restore CS0618 // Type or member is obsolete
45+
{
46+
if (EnableUnsafeBinaryFormatterInPropertyValueSerialization)
47+
{
48+
SerializeAs = serializeAs;
49+
}
50+
else
51+
{
52+
throw new NotSupportedException(Obsoletions.BinaryFormatterMessage);
53+
}
54+
}
4155
Attributes = attributes;
4256
ThrowOnErrorDeserializing = throwOnErrorDeserializing;
4357
ThrowOnErrorSerializing = throwOnErrorSerializing;

src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/SettingsPropertyValue.cs

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ private object Deserialize()
8888
// Attempt 1: Try creating from SerializedValue
8989
if (SerializedValue != null)
9090
{
91+
bool throwBinaryFormatterDeprecationException = false;
9192
try
9293
{
9394
if (SerializedValue is string)
@@ -96,10 +97,17 @@ private object Deserialize()
9697
}
9798
else
9899
{
99-
using (MemoryStream ms = new MemoryStream((byte[])SerializedValue))
100+
// Issue https://github.com/dotnet/runtime/issues/39295 tracks finding an alternative to BinaryFormatter
101+
if (SettingsProperty.EnableUnsafeBinaryFormatterInPropertyValueSerialization)
100102
{
101-
// Issue https://github.com/dotnet/runtime/issues/39295 tracks finding an alternative to BinaryFormatter
102-
value = (new BinaryFormatter()).Deserialize(ms);
103+
using (MemoryStream ms = new MemoryStream((byte[])SerializedValue))
104+
{
105+
value = (new BinaryFormatter()).Deserialize(ms);
106+
}
107+
}
108+
else
109+
{
110+
throwBinaryFormatterDeprecationException = true;
103111
}
104112
}
105113
}
@@ -124,6 +132,11 @@ private object Deserialize()
124132
}
125133
}
126134

135+
if (throwBinaryFormatterDeprecationException)
136+
{
137+
throw new NotSupportedException(Obsoletions.BinaryFormatterMessage);
138+
}
139+
127140
if (value != null && !Property.PropertyType.IsAssignableFrom(value.GetType())) // is it the correct type
128141
value = null;
129142
}
@@ -192,12 +205,21 @@ private static object GetObjectFromString(Type type, SettingsSerializeAs seriali
192205
// Convert based on the serialized type
193206
switch (serializeAs)
194207
{
208+
#pragma warning disable CS0618 // Type or member is obsolete
195209
case SettingsSerializeAs.Binary:
196-
byte[] buffer = Convert.FromBase64String(serializedValue);
197-
using (MemoryStream ms = new MemoryStream(buffer))
210+
#pragma warning restore CS0618 // Type or member is obsolete
211+
if (SettingsProperty.EnableUnsafeBinaryFormatterInPropertyValueSerialization)
198212
{
199-
// Issue https://github.com/dotnet/runtime/issues/39295 tracks finding an alternative to BinaryFormatter
200-
return (new BinaryFormatter()).Deserialize(ms);
213+
byte[] buffer = Convert.FromBase64String(serializedValue);
214+
using (MemoryStream ms = new MemoryStream(buffer))
215+
{
216+
// Issue https://github.com/dotnet/runtime/issues/39295 tracks finding an alternative to BinaryFormatter
217+
return (new BinaryFormatter()).Deserialize(ms);
218+
}
219+
}
220+
else
221+
{
222+
throw new NotSupportedException(Obsoletions.BinaryFormatterMessage);
201223
}
202224
case SettingsSerializeAs.Xml:
203225
StringReader sr = new StringReader(serializedValue);
@@ -218,15 +240,26 @@ private object SerializePropertyValue()
218240
if (_value == null)
219241
return null;
220242

243+
#pragma warning disable CS0618 // Type or member is obsolete
221244
if (Property.SerializeAs != SettingsSerializeAs.Binary)
245+
#pragma warning restore CS0618 // Type or member is obsolete
246+
{
222247
return ConvertObjectToString(_value, Property.PropertyType, Property.SerializeAs, Property.ThrowOnErrorSerializing);
248+
}
223249

224-
using (MemoryStream ms = new MemoryStream())
250+
if (SettingsProperty.EnableUnsafeBinaryFormatterInPropertyValueSerialization)
251+
{
252+
using (MemoryStream ms = new MemoryStream())
253+
{
254+
BinaryFormatter bf = new BinaryFormatter();
255+
// Issue https://github.com/dotnet/runtime/issues/39295 tracks finding an alternative to BinaryFormatter
256+
bf.Serialize(ms, _value);
257+
return ms.ToArray();
258+
}
259+
}
260+
else
225261
{
226-
// Issue https://github.com/dotnet/runtime/issues/39295 tracks finding an alternative to BinaryFormatter
227-
BinaryFormatter bf = new BinaryFormatter();
228-
bf.Serialize(ms, _value);
229-
return ms.ToArray();
262+
throw new NotSupportedException(Obsoletions.BinaryFormatterMessage);
230263
}
231264
}
232265

@@ -255,7 +288,9 @@ private static string ConvertObjectToString(object propertyValue, Type type, Set
255288

256289
xs.Serialize(sw, propertyValue);
257290
return sw.ToString();
291+
#pragma warning disable CS0618 // Type or member is obsolete
258292
case SettingsSerializeAs.Binary:
293+
#pragma warning restore CS0618 // Type or member is obsolete
259294
Debug.Fail("Should not have gotten here with Binary formatting");
260295
break;
261296
}

src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/SettingsSerializeAs.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System;
5+
46
namespace System.Configuration
57
{
68
public enum SettingsSerializeAs
79
{
810
String = 0,
911
Xml = 1,
12+
[Obsolete(Obsoletions.BinaryFormatterMessage + @". Consider using Xml instead.", false)]
1013
Binary = 2,
1114
ProviderSpecific = 3
1215
}

src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
<Compile Include="System\Configuration\ApplicationSettingsBaseTests.cs" />
6262
<Compile Include="System\Configuration\AppSettingsReaderTests.cs" />
6363
<Compile Include="System\Configuration\AppSettingsTests.cs" />
64+
<Compile Include="System\Configuration\BinaryFormatterDeprecationTests.cs" />
6465
<Compile Include="System\Configuration\CallBackValidatorAttributeTests.cs" />
6566
<Compile Include="System\Configuration\ConfigPathUtilityTests.cs" />
6667
<Compile Include="System\Configuration\ConfigurationElementCollectionTests.cs" />

src/libraries/System.Configuration.ConfigurationManager/tests/System/Configuration/ApplicationSettingsBaseTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,9 @@ public void Reload_SimpleSettings_Ok()
213213
[ReadOnly(false)]
214214
[SettingsGroupName("TestGroup")]
215215
[SettingsProvider(typeof(TestProvider))]
216+
#pragma warning disable CS0618 // Type or member is obsolete
216217
[SettingsSerializeAs(SettingsSerializeAs.Binary)]
218+
#pragma warning restore CS0618 // Type or member is obsolete
217219
private class SettingsWithAttributes : ApplicationSettingsBase
218220
{
219221
[ApplicationScopedSetting]
@@ -243,7 +245,9 @@ public void SettingsProperty_SettingsWithAttributes_Ok()
243245
Assert.Equal(1, settings.Properties.Count);
244246
SettingsProperty property = settings.Properties["StringProperty"];
245247
Assert.Equal(typeof(TestProvider), property.Provider.GetType());
248+
#pragma warning disable CS0618 // Type or member is obsolete
246249
Assert.Equal(SettingsSerializeAs.Binary, property.SerializeAs);
250+
#pragma warning restore CS0618 // Type or member is obsolete
247251
}
248252

249253
[Fact]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Configuration;
6+
using Microsoft.DotNet.RemoteExecutor;
7+
using Xunit;
8+
9+
namespace System.ConfigurationTests
10+
{
11+
public class BinaryFormatterDeprecationTests
12+
{
13+
private static bool AreBinaryFormatterAndRemoteExecutorSupportedOnThisPlatform => PlatformDetection.IsBinaryFormatterSupported && RemoteExecutor.IsSupported;
14+
15+
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "SettingsSerializeAs.Binary is deprecated only on Core")]
16+
[Fact]
17+
public void ThrowOnSettingsPropertyConstructorWithSettingsSerializeAsBinary()
18+
{
19+
#pragma warning disable CS0618 // Type or member is obsolete
20+
Assert.Throws<NotSupportedException>(() => new SettingsProperty("Binary", typeof(byte[]), null, false,"AString", SettingsSerializeAs.Binary, new SettingsAttributeDictionary(), true, true));
21+
#pragma warning restore CS0618 // Type or member is obsolete
22+
}
23+
24+
[ConditionalFact(nameof(AreBinaryFormatterAndRemoteExecutorSupportedOnThisPlatform))]
25+
public void SerializeAndDeserializeWithSettingsSerializeAsBinary()
26+
{
27+
RemoteInvokeOptions options = new RemoteInvokeOptions();
28+
options.RuntimeConfigurationOptions.Add("System.Configuration.ConfigurationManager.EnableUnsafeBinaryFormatterInPropertyValueSerialization", bool.TrueString);
29+
RemoteExecutor.Invoke(() =>
30+
{
31+
#pragma warning disable CS0618 // Type or member is obsolete
32+
SettingsProperty property = new SettingsProperty("Binary", typeof(string), null, false, "AString", SettingsSerializeAs.Binary, new SettingsAttributeDictionary(), true, true);
33+
#pragma warning restore CS0618 // Type or member is obsolete
34+
SettingsPropertyValue value = new SettingsPropertyValue(property);
35+
value.PropertyValue = "AString"; // To force _changedSinceLastSerialized to true to allow for serialization in the next call
36+
object serializedValue = value.SerializedValue;
37+
Assert.NotNull(serializedValue);
38+
value.Deserialized = false;
39+
object deserializedValue = value.PropertyValue;
40+
Assert.Equal("AString", deserializedValue);
41+
}, options).Dispose();
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)