ardalis / ardalis/SmartEnum

NativeAOT and trimming support

Open
#537 2 comments 1 reaction 0 assignees View on GitHub
enhancement
Dominant language
C#
Stars
2.4k
Forks
184
PR merge metrics
No merged PRs in 30d

Description

Firstly, let me open with my thanks for this library, I've only recently discovered it, but wish I'd found it earlier! 😄

I've had a minor issue in the project I'm working on, which is being compiled for native AOT. The following warning is displayed in VS:

```Assembly 'Ardalis.SmartEnum' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries```

And it didn't work as expected, due to my smart enum not being able to obtain values using the ```TryFromValue``` method.

I had a quick look at the source, and I suspected this was due to the use of reflection:

https://github.com/ardalis/SmartEnum/blob/0eae38b8e3273440ab07e8e815ba01436aa1f07a/src/SmartEnum/SmartEnum.cs#L70-L79

https://github.com/ardalis/SmartEnum/blob/0eae38b8e3273440ab07e8e815ba01436aa1f07a/src/SmartEnum/TypeExtensions.cs#L10-L16

I was successfully able to _hack_ around it, by adding the following to my enum, providing the hints to the IL to prevent it optimizing away the info needed to perform reflection.

```C#
[RequiresUnreferencedCode("Calls System.Reflection.Assembly.GetTypes()")]
public sealed class MySmartEnum : SmartEnum
{
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(MySmartEnum))]
public new static MySmartEnum FromName(string name, bool ignoreCase = false)
{
return SmartEnum.FromName(name, ignoreCase);
}

[DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(MySmartEnum))]
public new static MySmartEnum FromValue(Guid value)
{
return SmartEnum.FromValue(value);
}

[DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(MySmartEnum))]
public new static bool TryFromValue(Guid value, out MySmartEnum result)
{
return SmartEnum.TryFromValue(value, out result);
}

[DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(MySmartEnum))]
public new static bool TryFromName(string name, out MySmartEnum result)
{
return SmartEnum.TryFromName(name, out result);
}
}
```

Thought It would be beneficial to set these options in the source if possible, so the warnings are prevented, or at least open an issue for others to reference if they're in a similar situation.

Perhaps its also worth giving some consideration to the feasiblity of whether the use of reflection could be avoided entirely/optionally.

Could derived classes provide their own implementation of GetAllOptions, or perhaps theres another approach of handling the 'discoverability' of available options?

Could it be as simple as being 'registered' into the _enumOptions collection when being constructed?

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the reflection-related code in src/SmartEnum/SmartEnum.cs and src/SmartEnum/TypeExtensions.cs at the linked lines. Reproduce the trim warning and the failed TryFromValue behavior in a NativeAOT build, then determine whether the support should use trimming annotations or an alternative discovery approach. Done means the library works under NativeAOT without the reported warnings or failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
build-system
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.