-
Notifications
You must be signed in to change notification settings - Fork 6k
Description
[Breaking change]: Replace DAMT.All with more restricted annotation on InvokeMember/FindMembers/DeclaredMembers
Description
Starting in .NET 10.0, the System.Reflection
APIs InvokeMember
, FindMembers
, and DeclaredMembers
have been updated to use more restricted annotations instead of DAMT.All
. This change affects scenarios where developers implement the IReflect
interface or derive from System.TypeInfo
. The previous use of DAMT.All
was overly permissive and could lead to unintended behavior, such as capturing interface methods implemented by a class or generating warnings due to unsafe reflection calls.
This change improves the accuracy of annotations and ensures better compatibility with trimming and reflection scenarios. However, it introduces a breaking change for developers who have implemented IReflect
or derived from System.TypeInfo
, as they may need to update their annotations to align with the new behavior.
Version
.NET 10.0
Previous behavior
The InvokeMember
, FindMembers
, and DeclaredMembers
APIs used the DAMT.All
annotation, which was overly permissive. This could result in capturing additional members, such as interface methods implemented by a class, and potentially cause runtime warnings or unsafe reflection calls.
New behavior
The InvokeMember
, FindMembers
, and DeclaredMembers
APIs now use more restricted annotations, which provide better control over the members captured during reflection. Developers implementing IReflect
or deriving from System.TypeInfo
must update their annotations to match the new behavior.
Ex:
class MyType : IReflect
{
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields |
DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties |
DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public object InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target,
object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters)
{ }
}
Type of breaking change
- Source incompatible: When recompiled using .NET 10.0 or targeting the new runtime, existing source code may require changes to annotations to compile successfully.
- Behavioral change: Existing binaries might behave differently at runtime due to the updated annotations.
Reason for change
The change was introduced to improve the accuracy of annotations in System.Reflection
APIs and to address issues caused by the overly permissive DAMT.All
annotation. This ensures better compatibility with trimming and reflection scenarios, reduces runtime warnings, and prevents unsafe reflection calls.
Recommended action
Developers who implement IReflect
or derive from System.TypeInfo
should review their code and update annotations to align with the new behavior. Specifically:
- Replace
DAMT.All
annotations with more restricted annotations, such asDynamicallyAccessedMemberTypes.PublicMethods
,DynamicallyAccessedMemberTypes.NonPublicMethods
, or other appropriate types. - Test reflection scenarios to ensure that the updated annotations capture the intended members and do not introduce runtime errors or warnings.
Feature area
- Core .NET libraries
- System.Reflection
Affected APIs
System.Reflection.IReflect.InvokeMember
System.Reflection.IReflect.FindMembers
System.Reflection.TypeInfo.DeclaredMembers
Additional resources
For more information on DynamicallyAccessedMembers
annotations and their usage, refer to the Microsoft documentation on trimming and reflection.
Metadata
Metadata
Labels
Type
Projects
Status