Skip to content

Commit 92afc71

Browse files
authored
Disable default and ambient attribute at runtime with a feature switch (#100416)
* Disable default and ambient attribute at runtime with a feature switch * throwing at the getter at runtime
1 parent 3515c7a commit 92afc71

File tree

4 files changed

+63
-14
lines changed

4 files changed

+63
-14
lines changed

src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx

+3
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@
106106
<data name="NullableConverterBadCtorArg" xml:space="preserve">
107107
<value>The specified type is not a nullable type.</value>
108108
</data>
109+
<data name="RuntimeInstanceNotAllowed" xml:space="preserve">
110+
<value>Runtime instantiation of this attribute is not allowed.</value>
111+
</data>
109112
<data name="Text" xml:space="preserve">
110113
<value>(Text)</value>
111114
</data>

src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs

+34-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
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.ComponentModel.Design;
5+
using System.Diagnostics;
46
using System.Diagnostics.CodeAnalysis;
57

68
namespace System.ComponentModel
@@ -12,6 +14,11 @@ namespace System.ComponentModel
1214
[AttributeUsage(AttributeTargets.All)]
1315
public sealed class AmbientValueAttribute : Attribute
1416
{
17+
/// <summary>
18+
/// This is the default value.
19+
/// </summary>
20+
private object? _value;
21+
1522
/// <summary>
1623
/// Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class, converting the
1724
/// specified value to the specified type, and using the U.S. English culture as the
@@ -22,9 +29,15 @@ public AmbientValueAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemb
2229
{
2330
// The try/catch here is because attributes should never throw exceptions. We would fail to
2431
// load an otherwise normal class.
32+
33+
if (!IDesignerHost.IsSupported)
34+
{
35+
return;
36+
}
37+
2538
try
2639
{
27-
Value = TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value);
40+
_value = TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value);
2841
}
2942
catch
3043
{
@@ -37,7 +50,7 @@ public AmbientValueAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemb
3750
/// </summary>
3851
public AmbientValueAttribute(char value)
3952
{
40-
Value = value;
53+
_value = value;
4154
}
4255

4356
/// <summary>
@@ -46,7 +59,7 @@ public AmbientValueAttribute(char value)
4659
/// </summary>
4760
public AmbientValueAttribute(byte value)
4861
{
49-
Value = value;
62+
_value = value;
5063
}
5164

5265
/// <summary>
@@ -55,7 +68,7 @@ public AmbientValueAttribute(byte value)
5568
/// </summary>
5669
public AmbientValueAttribute(short value)
5770
{
58-
Value = value;
71+
_value = value;
5972
}
6073

6174
/// <summary>
@@ -64,7 +77,7 @@ public AmbientValueAttribute(short value)
6477
/// </summary>
6578
public AmbientValueAttribute(int value)
6679
{
67-
Value = value;
80+
_value = value;
6881
}
6982

7083
/// <summary>
@@ -73,7 +86,7 @@ public AmbientValueAttribute(int value)
7386
/// </summary>
7487
public AmbientValueAttribute(long value)
7588
{
76-
Value = value;
89+
_value = value;
7790
}
7891

7992
/// <summary>
@@ -82,7 +95,7 @@ public AmbientValueAttribute(long value)
8295
/// </summary>
8396
public AmbientValueAttribute(float value)
8497
{
85-
Value = value;
98+
_value = value;
8699
}
87100

88101
/// <summary>
@@ -91,7 +104,7 @@ public AmbientValueAttribute(float value)
91104
/// </summary>
92105
public AmbientValueAttribute(double value)
93106
{
94-
Value = value;
107+
_value = value;
95108
}
96109

97110
/// <summary>
@@ -100,15 +113,15 @@ public AmbientValueAttribute(double value)
100113
/// </summary>
101114
public AmbientValueAttribute(bool value)
102115
{
103-
Value = value;
116+
_value = value;
104117
}
105118

106119
/// <summary>
107120
/// Initializes a new instance of the <see cref='System.ComponentModel.AmbientValueAttribute'/> class using a <see cref='string'/>.
108121
/// </summary>
109122
public AmbientValueAttribute(string? value)
110123
{
111-
Value = value;
124+
_value = value;
112125
}
113126

114127
/// <summary>
@@ -117,13 +130,22 @@ public AmbientValueAttribute(string? value)
117130
/// </summary>
118131
public AmbientValueAttribute(object? value)
119132
{
120-
Value = value;
133+
_value = value;
121134
}
122135

123136
/// <summary>
124137
/// Gets the ambient value of the property this attribute is bound to.
125138
/// </summary>
126-
public object? Value { get; }
139+
public object? Value {
140+
get
141+
{
142+
if (!IDesignerHost.IsSupported)
143+
{
144+
throw new ArgumentException(SR.RuntimeInstanceNotAllowed);
145+
}
146+
return _value;
147+
}
148+
}
127149

128150
public override bool Equals([NotNullWhen(true)] object? obj)
129151
{

src/libraries/System.Private.CoreLib/src/Resources/Strings.resx

+4-1
Original file line numberDiff line numberDiff line change
@@ -3359,6 +3359,9 @@
33593359
<data name="RFLCT_Targ_StatMethReqTarg" xml:space="preserve">
33603360
<value>Non-static method requires a target.</value>
33613361
</data>
3362+
<data name="RuntimeInstanceNotAllowed" xml:space="preserve">
3363+
<value>Runtime instantiation of this attribute is not allowed.</value>
3364+
</data>
33623365
<data name="RuntimeWrappedException" xml:space="preserve">
33633366
<value>An object that does not derive from System.Exception has been wrapped in a RuntimeWrappedException.</value>
33643367
</data>
@@ -4313,4 +4316,4 @@
43134316
<data name="WasmThreads_BlockingWaitNotSupportedOnJSInterop" xml:space="preserve">
43144317
<value>Blocking wait is not supported on the JS interop threads.</value>
43154318
</data>
4316-
</root>
4319+
</root>

src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
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.Diagnostics;
45
using System.Diagnostics.CodeAnalysis;
56
using System.Globalization;
67
using System.Reflection;
@@ -22,6 +23,9 @@ public class DefaultValueAttribute : Attribute
2223
// Delegate ad hoc created 'TypeDescriptor.ConvertFromInvariantString' reflection object cache
2324
private static object? s_convertFromInvariantString;
2425

26+
[FeatureSwitchDefinition("System.ComponentModel.DefaultValueAttribute.IsSupported")]
27+
internal static bool IsSupported => AppContext.TryGetSwitch("System.ComponentModel.DefaultValueAttribute.IsSupported", out bool isSupported) ? isSupported : true;
28+
2529
/// <summary>
2630
/// Initializes a new instance of the <see cref='DefaultValueAttribute'/>
2731
/// class, converting the specified value to the specified type, and using the U.S. English
@@ -35,6 +39,12 @@ public DefaultValueAttribute(
3539
// The null check and try/catch here are because attributes should never throw exceptions.
3640
// We would fail to load an otherwise normal class.
3741

42+
if (!IsSupported)
43+
{
44+
Debug.Assert(!IsSupported, "Runtime instantiation of this attribute is not allowed.");
45+
return;
46+
}
47+
3848
if (type == null)
3949
{
4050
return;
@@ -229,7 +239,18 @@ public DefaultValueAttribute(ulong value)
229239
/// <summary>
230240
/// Gets the default value of the property this attribute is bound to.
231241
/// </summary>
232-
public virtual object? Value => _value;
242+
public virtual object? Value
243+
{
244+
get
245+
{
246+
if (!IsSupported)
247+
{
248+
throw new ArgumentException(SR.RuntimeInstanceNotAllowed);
249+
}
250+
return _value;
251+
}
252+
}
253+
233254

234255
public override bool Equals([NotNullWhen(true)] object? obj)
235256
{

0 commit comments

Comments
 (0)