Skip to content

Commit 9ff25a0

Browse files
BrianUnityEmandM
andauthored
fix: resolve core library types in IL post-processing under .NET reference assemblies (#4188)
PostProcessorReflectionImporter mapped System.Private.CoreLib types only to a referenced mscorlib or netstandard. Assemblies compiled against .NET reference assemblies (net10) reference neither, so imported types such as Guid stayed scoped to System.Private.CoreLib and Resolve() returned null. When the module references neither, scope the type to the referenced assembly that defines or forwards it. Co-authored-by: Emma <emma.mcmillan@unity3d.com>
1 parent e5f6047 commit 9ff25a0

2 files changed

Lines changed: 62 additions & 0 deletions

File tree

‎com.unity.netcode.gameobjects/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2323

2424
### Fixed
2525

26+
- Issue where the IL post-processor could not resolve core library types, such as `Guid` and `List<T>`, in assemblies compiled against .NET reference assemblies, for example when targeting .NET 10. Those split the core library across `System.Runtime`, `System.Collections` and other assemblies.
2627
- Fixed issue where a prefab added to a `NetworkPrefabsList` while a session was running was registered more than once and logged a duplicate `GlobalObjectIdHash` error. (#4184)
2728
- Issue where moving a `NetworkObject` into another scene made the clients that did not observe it log "Trying to synchronize NetworkObjectId but it was not spawned". The scene migration is now only sent to the clients that observe the `NetworkObject`. (#4176)
2829
- Issue where a `NetworkObject` that was moved into another scene while hidden from a client spawned in that client's active scene when it was shown with `NetworkShow`, instead of the scene it is in on the server. (#4176)

‎com.unity.netcode.gameobjects/Editor/CodeGen/PostProcessorReflectionImporter.cs‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
using System.Collections.Generic;
13
using System.Linq;
24
using System.Reflection;
35
using Mono.Cecil;
@@ -8,15 +10,74 @@ internal class PostProcessorReflectionImporter : DefaultReflectionImporter
810
{
911
private const string k_SystemPrivateCoreLib = "System.Private.CoreLib";
1012
private readonly AssemblyNameReference m_CorrectCorlib;
13+
private readonly Dictionary<string, AssemblyNameReference> m_CorlibTypeScopes = new Dictionary<string, AssemblyNameReference>();
1114

1215
public PostProcessorReflectionImporter(ModuleDefinition module) : base(module)
1316
{
1417
m_CorrectCorlib = module.AssemblyReferences.FirstOrDefault(a => a.Name == "mscorlib" || a.Name == "netstandard" || a.Name == k_SystemPrivateCoreLib);
1518
}
1619

20+
// .NET reference packs split System.Private.CoreLib across System.Runtime, System.Collections and others,
21+
// so a module that references none of the assemblies above needs the one that defines or forwards the type.
22+
protected override IMetadataScope ImportScope(Type type)
23+
{
24+
if (m_CorrectCorlib == null && type.Assembly.GetName().Name == k_SystemPrivateCoreLib)
25+
{
26+
var outermost = type;
27+
while (outermost.DeclaringType != null)
28+
{
29+
outermost = outermost.DeclaringType;
30+
}
31+
32+
var reference = FindReferenceDefining(outermost.FullName);
33+
if (reference != null)
34+
{
35+
return reference;
36+
}
37+
}
38+
39+
return base.ImportScope(type);
40+
}
41+
1742
public override AssemblyNameReference ImportReference(AssemblyName reference)
1843
{
1944
return m_CorrectCorlib != null && reference.Name == k_SystemPrivateCoreLib ? m_CorrectCorlib : base.ImportReference(reference);
2045
}
46+
47+
private AssemblyNameReference FindReferenceDefining(string fullName)
48+
{
49+
if (m_CorlibTypeScopes.TryGetValue(fullName, out var cached))
50+
{
51+
return cached;
52+
}
53+
54+
AssemblyNameReference found = null;
55+
foreach (var reference in module.AssemblyReferences)
56+
{
57+
AssemblyDefinition assembly;
58+
try
59+
{
60+
assembly = module.AssemblyResolver.Resolve(reference);
61+
}
62+
catch (AssemblyResolutionException)
63+
{
64+
continue;
65+
}
66+
67+
if (assembly == null)
68+
{
69+
continue;
70+
}
71+
72+
if (assembly.MainModule.GetType(fullName) != null || assembly.MainModule.ExportedTypes.Any(t => t.FullName == fullName))
73+
{
74+
found = reference;
75+
break;
76+
}
77+
}
78+
79+
m_CorlibTypeScopes[fullName] = found;
80+
return found;
81+
}
2182
}
2283
}

0 commit comments

Comments
 (0)