diff --git a/Dapper/DefaultTypeMap.cs b/Dapper/DefaultTypeMap.cs index c2f691883..2e3423485 100644 --- a/Dapper/DefaultTypeMap.cs +++ b/Dapper/DefaultTypeMap.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; @@ -33,6 +34,7 @@ internal static MethodInfo GetPropertySetterOrThrow(PropertyInfo propertyInfo, T static MethodInfo Throw(PropertyInfo propertyInfo) => throw new InvalidOperationException("Property setting not found for: " + propertyInfo?.Name); } + [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "The property was obtained from the mapped type and its setter must be preserved whenever the property is preserved.")] internal static MethodInfo? GetPropertySetter(PropertyInfo propertyInfo, Type type) { if (propertyInfo.DeclaringType == type) return propertyInfo.GetSetMethod(true); @@ -46,6 +48,7 @@ internal static MethodInfo GetPropertySetterOrThrow(PropertyInfo propertyInfo, T null)!.GetSetMethod(true); } + [UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "Dapper's runtime mapping contract requires the mapped type's properties to be preserved.")] internal static List GetSettableProps(Type t) { return t @@ -54,6 +57,7 @@ internal static List GetSettableProps(Type t) .ToList(); } + [UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "Dapper's runtime mapping contract requires the mapped type's fields to be preserved.")] private static FieldInfo[] GetSettableFields(Type t) { return t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); diff --git a/Dapper/NRT.cs b/Dapper/NRT.cs index 47c4366e6..b02fbb05b 100644 --- a/Dapper/NRT.cs +++ b/Dapper/NRT.cs @@ -1,6 +1,14 @@ #if !NET5_0_OR_GREATER namespace System.Diagnostics.CodeAnalysis { + [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] + internal sealed class UnconditionalSuppressMessageAttribute : Attribute + { + public UnconditionalSuppressMessageAttribute(string category, string checkId) { } + + public string? Justification { get; set; } + } + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class NotNullWhenAttribute : Attribute { diff --git a/Dapper/SqlDataRecordListTVPParameter.cs b/Dapper/SqlDataRecordListTVPParameter.cs index 28a6ab27c..90fc6a588 100644 --- a/Dapper/SqlDataRecordListTVPParameter.cs +++ b/Dapper/SqlDataRecordListTVPParameter.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Data; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Reflection.Emit; @@ -64,6 +65,8 @@ private static Action GetUDT(Type type) } } + [UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "The provider parameter type is only known at runtime and must preserve its public properties.")] + [UnconditionalSuppressMessage("Aot", "IL3050", Justification = "This fallback is only used for provider-specific structured parameters and is not supported by Dapper's AOT interceptors.")] static Action CreateFor(Type type, string nameProperty, int sqlDbType) { var name = type.GetProperty(nameProperty, BindingFlags.Public | BindingFlags.Instance); diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 98560add3..8f3956cab 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -365,6 +365,7 @@ public static void AddTypeHandlerImpl(Type type, ITypeHandler? handler, bool clo AddTypeHandlerCore(type, handler, true); // do not allow suppress clone } + [UnconditionalSuppressMessage("Aot", "IL3050", Justification = "Runtime type-handler registration requires the caller to statically root the corresponding TypeHandlerCache instantiation.")] private static void AddTypeHandlerCore(Type type, ITypeHandler? handler, bool clone) { if (type is null) throw new ArgumentNullException(nameof(type)); @@ -458,6 +459,7 @@ public static void SetDbType(IDataParameter parameter, object value) [Obsolete(ObsoleteInternalUsageOnly, false)] [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] + [UnconditionalSuppressMessage("Aot", "IL3050", Justification = "Runtime generic construction is limited to the optional SQL data-record handler path, which is not supported by Dapper's AOT interceptors.")] public static DbType? LookupDbType(Type type, string name, bool demand, out ITypeHandler? handler) { handler = null; @@ -2554,6 +2556,8 @@ private static bool IsValueTuple(Type? type) => (type?.IsValueType == true && type.FullName?.StartsWith("System.ValueTuple`", StringComparison.Ordinal) == true) || (type is not null && IsValueTuple(Nullable.GetUnderlyingType(type))); + [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "The runtime parameter generator requires the parameter object's public properties and constructors to be preserved.")] + [UnconditionalSuppressMessage("Aot", "IL3050", Justification = "This runtime parameter generator is a fallback for non-intercepted calls and is not used by generated AOT code.")] internal static Action CreateParamInfoGenerator(Identity identity, bool checkForDuplicates, bool removeUnused, IList literals) { Type type = identity.ParametersType!; diff --git a/Dapper/TypeExtensions.cs b/Dapper/TypeExtensions.cs index eb0efcbc9..812c30325 100644 --- a/Dapper/TypeExtensions.cs +++ b/Dapper/TypeExtensions.cs @@ -1,10 +1,12 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace Dapper { internal static class TypeExtensions { + [UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "All callers use framework types whose public methods are preserved.")] public static MethodInfo? GetPublicInstanceMethod(this Type type, string name, Type[] types) => type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public, null, types, null); }