Skip to content

Make projects AOT compatible#10006

Merged
NikolaMilosavljevic merged 1 commit intodotnet:mainfrom
NikolaMilosavljevic:aot.compatible
Mar 23, 2026
Merged

Make projects AOT compatible#10006
NikolaMilosavljevic merged 1 commit intodotnet:mainfrom
NikolaMilosavljevic:aot.compatible

Conversation

@NikolaMilosavljevic
Copy link
Copy Markdown
Member

@NikolaMilosavljevic NikolaMilosavljevic commented Mar 17, 2026

Contributes to #9193

Summary of changes.

1. Enable AOT compatibility analyzers on all src/ projects

Each .csproj under src/ received:

<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>

The condition restricts it to .NET Core TFMs, avoiding errors on netstandard2.0 / net472.

2. Replace reflection-based JSON serialization with source-generated contexts

Three new JsonSerializerContext files were added to eliminate AOT-unsafe JsonSerializer.Serialize(obj) calls:

New file Serializable type
GlobalSettingsJsonSerializerContext.cs GlobalSettingsData
SettingsStoreJsonSerializerContext.cs SettingsStore
TemplateCacheJsonSerializerContext.cs TemplateCache

The callers in GlobalSettings.cs, ComponentManager.cs, and TemplatePackageManager.cs were updated to use the new typed WriteObject<T> overload with JsonTypeInfo<T>.

3. Convert WriteObject to a type-safe generic

In JExtensions.cs, the untyped WriteObject(string, object) was replaced with:

WriteObject<T>(string path, T obj, JsonTypeInfo<T> jsonTypeInfo)

This uses JsonSerializer.Serialize(stream, obj, jsonTypeInfo) — fully AOT-safe.

4. Source-gen context for JsonEncodeValueFormFactory

In JsonEncodeValueFormFactory.cs, the static JsonSerializerOptions + JsonSerializer.Serialize(value, options) was replaced with a JsonEncodeSerializerContext using [JsonSerializable(typeof(string))], calling JsonSerializer.Serialize(value, context.String).

5. AOT suppression attributes on reflection-heavy methods

Methods that inherently use reflection (assembly loading, Type.GetType(), Activator.CreateInstance) received method-level [UnconditionalSuppressMessage] attributes with specific IL warning codes:

File Methods annotated Warning codes
ComponentManager.cs Constructor, TryGetComponent<T>, RegisterType, GetType IL2026, IL2057, IL2067, IL2070, IL2072, IL3000, IL3050
Scanner.cs ScanForComponents, LoadAllFromPath IL2026
ReflectionLoadProbingPath.cs SelectBestMatch, Resolving IL2026
Bootstrapper.cs Register(Assembly) IL2026

6. AOT annotations on remaining unsafe shared methods

ToJsonString(object) and FromObject(object) in JExtensions.cs received [RequiresUnreferencedCode] + [RequiresDynamicCode] attributes, propagating warnings to callers. The callers in TemplateSearchCache.Json.cs, TemplateSearchData.Json.cs, TemplatePackageSearchData.Json.cs, and TemplateDiscoveryMetadata.cs received corresponding [UnconditionalSuppressMessage] attributes with justifications.

All attributes are guarded with #if NET7_0_OR_GREATER (or #if NET where appropriate) so they compile cleanly on older TFMs.

@NikolaMilosavljevic NikolaMilosavljevic merged commit 97a3783 into dotnet:main Mar 23, 2026
8 checks passed
mmitche pushed a commit to dotnet/sdk that referenced this pull request Apr 2, 2026
Contributes to dotnet/templating#9193

Summary of changes.

## 1. Enable AOT compatibility analyzers on all `src/` projects

Each `.csproj` under `src/` received:

```xml
<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>
```

The condition restricts it to .NET Core TFMs, avoiding errors on
`netstandard2.0` / `net472`.

## 2. Replace reflection-based JSON serialization with source-generated
contexts

Three new `JsonSerializerContext` files were added to eliminate
AOT-unsafe `JsonSerializer.Serialize(obj)` calls:

| New file | Serializable type |
|---|---|
| `GlobalSettingsJsonSerializerContext.cs` | `GlobalSettingsData` |
| `SettingsStoreJsonSerializerContext.cs` | `SettingsStore` |
| `TemplateCacheJsonSerializerContext.cs` | `TemplateCache` |

The callers in `GlobalSettings.cs`, `ComponentManager.cs`, and
`TemplatePackageManager.cs` were updated to use the new typed
`WriteObject<T>` overload with `JsonTypeInfo<T>`.

## 3. Convert `WriteObject` to a type-safe generic

In `JExtensions.cs`, the untyped `WriteObject(string, object)` was
replaced with:

```csharp
WriteObject<T>(string path, T obj, JsonTypeInfo<T> jsonTypeInfo)
```

This uses `JsonSerializer.Serialize(stream, obj, jsonTypeInfo)` — fully
AOT-safe.

## 4. Source-gen context for `JsonEncodeValueFormFactory`

In `JsonEncodeValueFormFactory.cs`, the static `JsonSerializerOptions` +
`JsonSerializer.Serialize(value, options)` was replaced with a
`JsonEncodeSerializerContext` using
`[JsonSerializable(typeof(string))]`, calling
`JsonSerializer.Serialize(value, context.String)`.

## 5. AOT suppression attributes on reflection-heavy methods

Methods that inherently use reflection (assembly loading,
`Type.GetType()`, `Activator.CreateInstance`) received method-level
`[UnconditionalSuppressMessage]` attributes with specific IL warning
codes:

| File | Methods annotated | Warning codes |
|---|---|---|
| `ComponentManager.cs` | Constructor, `TryGetComponent<T>`,
`RegisterType`, `GetType` | IL2026, IL2057, IL2067, IL2070, IL2072,
IL3000, IL3050 |
| `Scanner.cs` | `ScanForComponents`, `LoadAllFromPath` | IL2026 |
| `ReflectionLoadProbingPath.cs` | `SelectBestMatch`, `Resolving` |
IL2026 |
| `Bootstrapper.cs` | `Register(Assembly)` | IL2026 |

## 6. AOT annotations on remaining unsafe shared methods

`ToJsonString(object)` and `FromObject(object)` in `JExtensions.cs`
received `[RequiresUnreferencedCode]` + `[RequiresDynamicCode]`
attributes, propagating warnings to callers. The callers in
`TemplateSearchCache.Json.cs`, `TemplateSearchData.Json.cs`,
`TemplatePackageSearchData.Json.cs`, and `TemplateDiscoveryMetadata.cs`
received corresponding `[UnconditionalSuppressMessage]` attributes with
justifications.

All attributes are guarded with `#if NET7_0_OR_GREATER` (or `#if NET`
where appropriate) so they compile cleanly on older TFMs.

Commit migrated from dotnet/templating@97a3783
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants