Skip to content

Commit 62d11ed

Browse files
authored
Merge pull request #290 from ifBars/diffuin/289-2d87c4ca
2 parents 1354b99 + f8ab166 commit 62d11ed

2 files changed

Lines changed: 53 additions & 2 deletions

File tree

S1API.Tests/Internal/Utils/ReflectionUtilsTests.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,46 @@ public void DerivedTypeScanFollowsTransitiveAssemblyReferences()
9191
loadedAssemblies));
9292
}
9393

94+
[Fact]
95+
public void DerivedTypeScanDoesNotFollowSameNameAssembliesWithDifferentIdentities()
96+
{
97+
string assemblyName = $"S1API.ReflectionUtilsTests.Duplicate.{Guid.NewGuid():N}";
98+
AssemblyBuilder unrelatedAssembly = CreateDynamicAssembly(assemblyName, new Version(1, 0, 0, 0));
99+
Type unrelatedType = unrelatedAssembly
100+
.DefineDynamicModule(assemblyName)
101+
.DefineType("UnrelatedType", TypeAttributes.Public)
102+
.CreateType()!;
103+
104+
AssemblyBuilder relatedAssembly = CreateDynamicAssembly(assemblyName, new Version(2, 0, 0, 0));
105+
relatedAssembly
106+
.DefineDynamicModule(assemblyName)
107+
.DefineType("RelatedType", TypeAttributes.Public, typeof(ReflectionCandidateBridge))
108+
.CreateType();
109+
110+
AssemblyBuilder candidateAssembly = CreateDynamicAssembly(
111+
$"S1API.ReflectionUtilsTests.Candidate.{Guid.NewGuid():N}",
112+
new Version(1, 0, 0, 0));
113+
ModuleBuilder candidateModule = candidateAssembly.DefineDynamicModule(candidateAssembly.GetName().Name!);
114+
candidateModule
115+
.DefineType("CandidateType", TypeAttributes.Public, unrelatedType)
116+
.CreateType();
117+
118+
Assert.False(ReflectionUtils.CanContainTypesDerivedFrom(
119+
candidateAssembly,
120+
typeof(ReflectionUtils).Assembly,
121+
AppDomain.CurrentDomain.GetAssemblies()));
122+
}
123+
124+
private static AssemblyBuilder CreateDynamicAssembly(string name, Version version)
125+
{
126+
var assemblyName = new AssemblyName(name)
127+
{
128+
Version = version
129+
};
130+
131+
return AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
132+
}
133+
94134
private sealed class MonoShape
95135
{
96136
#pragma warning disable CS0169

S1API/Internal/Utils/ReflectionUtils.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ private static bool CanContainTypesDerivedFrom(
106106
AssemblyName baseAssemblyName,
107107
IReadOnlyDictionary<string, Assembly[]> assembliesBySimpleName)
108108
{
109-
if (AssemblyName.ReferenceMatchesDefinition(candidateAssembly.GetName(), baseAssemblyName))
109+
if (AssemblyIdentityMatches(candidateAssembly.GetName(), baseAssemblyName))
110110
return true;
111111

112112
return ReferencesAssemblyTransitively(
@@ -137,7 +137,7 @@ private static bool ReferencesAssemblyTransitively(
137137

138138
foreach (AssemblyName referencedAssembly in referencedAssemblies)
139139
{
140-
if (AssemblyName.ReferenceMatchesDefinition(referencedAssembly, baseAssemblyName))
140+
if (AssemblyIdentityMatches(referencedAssembly, baseAssemblyName))
141141
return true;
142142

143143
string referencedName = referencedAssembly.Name ?? string.Empty;
@@ -147,6 +147,9 @@ private static bool ReferencesAssemblyTransitively(
147147

148148
foreach (Assembly loadedReference in loadedReferences)
149149
{
150+
if (!AssemblyIdentityMatches(loadedReference.GetName(), referencedAssembly))
151+
continue;
152+
150153
if (ReferencesAssemblyTransitively(
151154
loadedReference,
152155
baseAssemblyName,
@@ -161,6 +164,14 @@ private static bool ReferencesAssemblyTransitively(
161164
return false;
162165
}
163166

167+
private static bool AssemblyIdentityMatches(
168+
AssemblyName referenceAssemblyName,
169+
AssemblyName definitionAssemblyName) =>
170+
string.Equals(
171+
referenceAssemblyName.FullName,
172+
definitionAssemblyName.FullName,
173+
StringComparison.OrdinalIgnoreCase);
174+
164175
/// <summary>
165176
/// INTERNAL: Gets all types by their name.
166177
/// </summary>

0 commit comments

Comments
 (0)