dotnet / dotnet/runtime

[Microsoft.XmlSerializer.Generator] Throws on internal types even when generated assembly is in the same scope

Open
#125,968 0 comments 5 reactions 0 assignees View on GitHub
area-Serialization untriaged
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Description

The generator does not generate serializers for `internal` types, even though the generated `XmlSerializers` code runs in the same assembly and can access them.

### Reproduction Steps

1. Create a new console project:
```bash
dotnet new console -o MyApp
```
2. Add the NuGet package and CLI tool reference:
```bash
dotnet add package Microsoft.XmlSerializer.Generator
```
Then add to `MyApp.csproj`:
```csproj

true


```
3. Replace `Program.cs` with:
```csharp
using System.Reflection;

public static class Program
{
public static void Main()
{
var instance = new MyInternalClass
{
Value = "Hello, World!"
};

var serializer = Assembly
.LoadFrom(Path.Combine(AppContext.BaseDirectory, "MyApp.XmlSerializers.dll"))
.CreateInstance("Microsoft.Xml.Serialization.GeneratedAssembly.MyInternalClassSerializer");

Console.WriteLine(instance.Value);
Console.WriteLine(serializer);
}
}

internal class MyInternalClass
{
public required string Value;
}
```

4. Run with `internal` - observe the warning and that `serializer` is `null`:
```bash
dotnet run -v detailed
```

### Expected behavior

The generator creates `XmlSerializers` correctly, since the generated code is compiled within the same assembly scope and can process `internal` types.

### Actual behavior

Build log shows generator ignoring `MyInternalClass`:
```bash
Importing MyInternalClass (3/3)
Ignoring 'MyInternalClass'.
MyInternalClass is inaccessible due to its protection level. Only public types can be processed.
```

### Regression?

_No response_

### Known Workarounds

It is possible to temporarily change `internal` to `public` and run generation:
```bash
dotnet run
```
Then switch back to `internal` and run without rebuilding:
```bash
dotnet run --no-build
```
However, this only works until the next build, after which the issue reappears. This proves that the generated serializer has no runtime issues with `internal` types.

### Configuration

- .NET 10
- Windows 10.0.26200
- x64

### Other information

In `System.Private.Xml` internal types are rejected too early, even when they are actually visible from the generated code context. The issue is caused by this check in [Types.cs](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Types.cs#L826), which blindly rejects the internal type based on accessibility, without accounting for cases where the type is still visible/usable.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.