Skip to content

Workaround single trimming warning. #1499

Closed
@artyomszasa

Description

@artyomszasa

Is your feature request related to a problem? Please describe

When using Trimming and/or AOT while targeting .NET8 Magick.NET.Core emits single warning:

/_/src/Shared/TypeHelper.cs(20): Trim analysis warning IL2075: ImageMagick.TypeHelper.GetCustomAttributes<T>(Enum): 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicFields' in call to 'System.Type.GetField(String)'. The return value of method 'System.Object.GetType()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

IMHO (see alternatives) it is not critical yet workarounding this would make the warning go away making "using Magick.NET" experience event greater.

Describe the solution you'd like

Looking at the code (https://github.com/dlemstra/Magick.NET/blob/main/src/Shared/TypeHelper.cs) IMHO it can be easily avoided by adding DynamicallyAccessedMembersAttribute to the type parameter.
I am aware Magick.NET is targeting nestandard thus built-in attributes are not available, yet it can be workarounded by adding own internal attribute(s) that are sematically equal to the ones the compiler is using:

namespace System.Diagnostics.CodeAnalysis
{
    //
    // Summary:
    //     Specifies the types of members that are dynamically accessed. This enumeration
    //     has a System.FlagsAttribute attribute that allows a bitwise combination of its
    //     member values.
    [Flags]
    internal enum DynamicallyAccessedMemberTypes
    {
        //
        // Summary:
        //     Specifies all members.
        All = -1,
        //
        // Summary:
        //     Specifies no members.
        None = 0,
        //
        // Summary:
        //     Specifies the default, parameterless public constructor.
        PublicParameterlessConstructor = 1,
        //
        // Summary:
        //     Specifies all public constructors.
        PublicConstructors = 3,
        //
        // Summary:
        //     Specifies all non-public constructors.
        NonPublicConstructors = 4,
        //
        // Summary:
        //     Specifies all public methods.
        PublicMethods = 8,
        //
        // Summary:
        //     Specifies all non-public methods.
        NonPublicMethods = 16,
        //
        // Summary:
        //     Specifies all public fields.
        PublicFields = 32,
        //
        // Summary:
        //     Specifies all non-public fields.
        NonPublicFields = 64,
        //
        // Summary:
        //     Specifies all public nested types.
        PublicNestedTypes = 128,
        //
        // Summary:
        //     Specifies all non-public nested types.
        NonPublicNestedTypes = 256,
        //
        // Summary:
        //     Specifies all public properties.
        PublicProperties = 512,
        //
        // Summary:
        //     Specifies all non-public properties.
        NonPublicProperties = 1024,
        //
        // Summary:
        //     Specifies all public events.
        PublicEvents = 2048,
        //
        // Summary:
        //     Specifies all non-public events.
        NonPublicEvents = 4096,
        //
        // Summary:
        //     Specifies all interfaces implemented by the type.
        Interfaces = 8192
    }

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)]
    internal sealed class DynamicallyAccessedMembersAttribute : Attribute
    {
        public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
        {
            MemberTypes = memberTypes;
        }

        public DynamicallyAccessedMemberTypes MemberTypes { get; }
    }
}

Describe alternatives you've considered

As I can see from code the affected member is used almost only here: https://github.com/dlemstra/Magick.NET/blob/main/src/Magick.NET.Core/Profiles/Exif/Values/ExifValue%7BTValueType%7D.cs#L59

So adding dynamic dependency to the internal attribute (using stringified singnature) makes trimming/aot perfectly safe, yet the warning persists making it impossible to achive warningless AOT build.

Additional context

Trimming and AOT are IMHO great features of the .NET and I think (and hope) it will be pushed by Microsoft in all further versions of the .NET. A lot of libraries are not Trim/AOT compatible (yet?) but the Magick.NET actually is compatible out-of-box, yet the single warning making the whole library is reported to be not compatible with Trimming/AOT...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions