0

In the bellow code for line

ConstructorInfo constructorInfoObj = ValueType.GetConstructor(Type.EmptyTypes);

I get this warning:

ValueDescriptor.cs(58, 50): [IL2080] 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Type.GetConstructor(Type[])'. The field 'MigraDocCore.DocumentObjectModel.Internals.ValueDescriptor.ValueType' 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.

This only occurs if I add

<IsTrimmable>true</IsTrimmable>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>

to the .csproj-file.

Why is this warning thrown, and what has it to do with trimmable ?
How to remedy this without removing IsTrimmable and without setting EnableTrimAnalyzer to false ?

This is the code for context:

using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;

namespace MigraDocCore.DocumentObjectModel.Internals
{
    /// <summary>
    /// Base class of all value descriptor classes.
    /// </summary>
    public abstract class ValueDescriptor
    {
        public Type ValueType;

        internal ValueDescriptor(Type valueType)
        {
            this.ValueType = valueType;
        }

        public object CreateValue()
        {
            ConstructorInfo constructorInfoObj = ValueType.GetConstructor(Type.EmptyTypes);
            
            return constructorInfoObj.Invoke(null);
        }
        
        // [...]
    }
}

Full source of this class: https://github.com/ststeiger/PdfSharpCore/blob/master/MigraDocCore.DocumentObjectModel/MigraDoc.DocumentObjectModel.Internals/ValueDescriptor.cs#L58

Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
  • What is `ValueType.GetConstructor`? Can you please provide a full [mre]? – Guru Stron Apr 18 '23 at 15:06
  • 2
    _"Why is this warning thrown, and what has it to do with trimmable ?"_ - you have enabled trimming which will trim parts which are considered unused by the compiler, which obviously can affect the reflection code, hence the warning (note that compiler can give quite some false positives here). Some details can be found [here](https://stackoverflow.com/q/75672166/2501279). – Guru Stron Apr 18 '23 at 15:09
  • Guru Stron: Sorry, missed that. ValueType is just a field of type System.Type in class ValueDescriptor. – Stefan Steiger Apr 18 '23 at 15:41
  • And no attributes attached to that property? – Ralf Apr 18 '23 at 15:42
  • @Ralf: Yep, no attributes. For reference: https://github.com/ststeiger/PdfSharpCore/blob/master/MigraDocCore.DocumentObjectModel/MigraDoc.DocumentObjectModel.Internals/ValueDescriptor.cs#L58 – Stefan Steiger Apr 18 '23 at 15:42
  • I was doing something similar and in my case that one was a false positive, so I just ignored it (have tested against published version). – Guru Stron Apr 18 '23 at 15:47
  • You may try adding `[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]`. Asp.Net does it for its startup type also. See https://source.dot.net/#Microsoft.AspNetCore.Hosting.Abstractions/HostingStartupAttribute.cs,34 – Ralf Apr 18 '23 at 15:55
  • @Ralf: No you cannot, DynamicallyAccessedMembers is internal, not public. – Stefan Steiger Apr 18 '23 at 16:24
  • @StefanSteiger you can try other options from corresponding enum, like `NonPublicConstructors | PublicConstructors` – Guru Stron Apr 18 '23 at 16:37
  • The warning is real enough, the diagnostic is however not accurate. You need to watch out, this code can easily fail after trimming. When the type that the ValueType member refers to got eliminated. The code analyzer otherwise can't figure out exactly what type might cause the problem, all it sees is Type, and fumbles to assuming it might be ValueDescriptor. This code just isn't all that safe to trim, if you are going to use it then you'll need to test thoroughly. Consider filing a bug report. – Hans Passant Apr 18 '23 at 18:00

1 Answers1

0

So fix can look like:

internal ValueDescriptor(string valueName, 
    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type valueType, 
    Type memberType,
    MemberInfo memberInfo,
    VDFlags flags)
{
    this.ValueType = valueType;
    // ...
}

/// <summary>
/// Type of the described value, e.g. typeof(Int32) for an NInt.
/// </summary>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public Type ValueType;

But then you will need to propagate the attribute to all places where it will be used (also the attribute and the enum should be public).

Guru Stron
  • 102,774
  • 10
  • 95
  • 132