Skip to content

Commit

Permalink
[release/7.0] Fix Equals in hot reload scenario (#78258)
Browse files Browse the repository at this point in the history
* Fix Equals in hot reload scenario

* Update src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs

Co-authored-by: Steve Harter <steveharter@users.noreply.github.com>

Co-authored-by: Buyaa Namnan <bunamnan@microsoft.com>
Co-authored-by: Buyaa Namnan <buyankhishig.namnan@microsoft.com>
Co-authored-by: Steve Harter <steveharter@users.noreply.github.com>
  • Loading branch information
4 people authored Nov 14, 2022
1 parent 1c341de commit 5397399
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ o is MdFieldInfo m &&

public override bool Equals(object? obj) =>
ReferenceEquals(this, obj) ||
(MetadataUpdater.IsSupported && CacheEquals(obj));
(MetadataUpdater.IsSupported &&
obj is MdFieldInfo fi &&
fi.m_tkField == m_tkField &&
ReferenceEquals(fi.m_declaringType, m_declaringType) &&
ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));

public override int GetHashCode() =>
HashCode.Combine(m_tkField.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ internal override RuntimeModule GetRuntimeModule()

public override bool Equals(object? obj) =>
ReferenceEquals(this, obj) ||
(MetadataUpdater.IsSupported && CacheEquals(obj));
(MetadataUpdater.IsSupported &&
obj is RtFieldInfo fi &&
fi.m_fieldHandle == m_fieldHandle &&
ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));

public override int GetHashCode() =>
HashCode.Combine(m_fieldHandle.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ public override string ToString()

public override bool Equals(object? obj) =>
ReferenceEquals(this, obj) ||
(MetadataUpdater.IsSupported && CacheEquals(obj));
(MetadataUpdater.IsSupported &&
obj is RuntimeEventInfo ei &&
ei.m_token == m_token &&
ReferenceEquals(ei.m_declaringType, m_declaringType) &&
ReferenceEquals(ei.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));

public override int GetHashCode() =>
HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,10 @@ public override IList<CustomAttributeData> GetCustomAttributesData()

public override bool Equals(object? obj) =>
ReferenceEquals(this, obj) ||
(MetadataUpdater.IsSupported && CacheEquals(obj));
(MetadataUpdater.IsSupported && obj is RuntimePropertyInfo rpi &&
rpi.m_token == m_token &&
ReferenceEquals(rpi.m_declaringType, m_declaringType) &&
ReferenceEquals(rpi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));

public override int GetHashCode() =>
HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@

namespace System.Reflection.Tests
{
public class A
{
public string P { get; set; }
public int F;
#pragma warning disable CS0067
public event EventHandler E;
#pragma warning restore CS0067
public void M() { }
}

[Collection(nameof(DisableParallelization))]
public class ReflectionCacheTests
public class ReflectionCacheTests : A
{
private static bool IsMetadataUpdateAndRemoteExecutorSupported => PlatformDetection.IsMetadataUpdateSupported && RemoteExecutor.IsSupported;

Expand Down Expand Up @@ -47,6 +57,12 @@ public void GetMembers_MultipleCalls_SameObjects()
AssertSameEqualAndHashCodeEqual(fi1, fi2);
AssertSameEqualAndHashCodeEqual(ei1, ei2);
AssertSameEqualAndHashCodeEqual(ci1, ci2);

PropertyInfo parentProperty = typeof(A).GetProperty("P");
PropertyInfo childProperty = s_type.GetProperty("P");
Assert.NotNull(parentProperty);
Assert.NotNull(childProperty);
Assert.NotEqual(parentProperty, childProperty);
}

void AssertSameEqualAndHashCodeEqual(object o1, object o2)
Expand Down Expand Up @@ -87,6 +103,20 @@ public void GetMembers_MultipleCalls_ClearCache_ReflectionCacheTestsType()
EventInfo ei1 = s_type.GetEvent(nameof(Event1));
ConstructorInfo ci1 = s_type.GetConstructor(Type.EmptyTypes);
PropertyInfo parentProperty = typeof(A).GetProperty("P");
PropertyInfo childProperty = s_type.GetProperty("P");
FieldInfo parentField = typeof(A).GetField("F");
FieldInfo childField = s_type.GetField("F");
MethodInfo parentMethod = typeof(A).GetMethod("M");
MethodInfo childMethod = s_type.GetMethod("M");
EventInfo parentEvent = typeof(A).GetEvent("E");
EventInfo childEvent = s_type.GetEvent("E");
Assert.NotEqual(parentProperty, childProperty);
Assert.NotEqual(parentField, childField);
Assert.NotEqual(parentMethod, childMethod);
Assert.NotEqual(parentEvent, childEvent);
clearCache(new[] { typeof(ReflectionCacheTests) });
MethodInfo mi2 = s_type.GetMethod(nameof(Method));
Expand All @@ -95,6 +125,11 @@ public void GetMembers_MultipleCalls_ClearCache_ReflectionCacheTestsType()
EventInfo ei2 = s_type.GetEvent(nameof(Event1));
ConstructorInfo ci2 = s_type.GetConstructor(Type.EmptyTypes);
Assert.NotEqual(parentProperty, childProperty);
Assert.NotEqual(parentField, childField);
Assert.NotEqual(parentMethod, childMethod);
Assert.NotEqual(parentEvent, childEvent);
AssertNotSameSameButEqualAndHashCodeEqual(mi1, mi2);
AssertNotSameSameButEqualAndHashCodeEqual(pi1, pi2);
AssertNotSameSameButEqualAndHashCodeEqual(fi1, fi2);
Expand Down

0 comments on commit 5397399

Please sign in to comment.