-
Notifications
You must be signed in to change notification settings - Fork 472
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proxy created with CreateClassProxyWithTarget returns false for Equals on itself #652
Comments
I discovered is has to do with Replacing We are throwing the proxies into a Dictionary - we can avoid this problem using a ReferenceEquals IEqualityComparer implementation. But since our case is library code, I'm not sure how downstream code uses the proxied instances, they could have their own dependency on Equals to return true for |
Hi @Gonyoda, and sorry for the slow reply. What you're observing is caused by #571, which got merged and first released in version 5.0.0 of this library. Because your proxy does not intercept I don't think that short of reverting the change we made in #571, there's not really anything we can do here. (But it's unlikely we want to reverse this, it'll just re-cause other issues that have been resolved by it.) What you could consider doing is to intercept the public class EqualsTargetInterceptor : IInterceptor
{
private static MethodInfo equalsMethod = typeof(object).GetMethod("Equals", BindingFlags.Public | BindingFlags.Instance);
public void Intercept(IInvocation invocation)
{
if (invocation.Method == equalsMethod)
{
invocation.ReturnValue = object.ReferenceEquals(invocation.Proxy, invocation.Arguments[0]);
// ^^^^^^^^^^^^^^^^
// instead of invocation.InvocationTarget
}
else
{
invocation.Proceed();
}
}
} You'd also need to use a custom [Serializable]
public class InterceptEqualsHook : AllMethodsHook
{
private static MethodInfo equalsMethod = typeof(object).GetMethod("Equals", BindingFlags.Public | BindingFlags.Instance);
public override bool ShouldInterceptMethod(Type type, MethodInfo method)
{
return base.ShouldInterceptMethod(type, method) || method == equalsMethod;
}
} Then use these components during proxy generation: -var proxy = proxyGen.CreateClassProxyWithTarget(entityType, entity);
+var proxy = proxyGen.CreateClassProxyWithTarget(entityType, entity, new ProxyGenerationOptions { Hook = new InterceptEqualsHook() }, new EqualsTargetInterceptor()); Please let me know whether this is helpful, otherwise I'll close this issue in a two weeks' time or thereabouts. |
Thank you for the detailed reply explaining why this is happening! I agree that changing it back is not a good solution. But I will leave this here as to our solution for storing proxies in a Dictionary. First was to make an sealed class ReferenceEquality : IEqualityComparer<object>
{
bool IEqualityComparer<object>.Equals(object? x, object? y) =>
ReferenceEquals(x, y);
int IEqualityComparer<object>.GetHashCode(object obj) =>
obj.GetHashCode();
} Dictionary declaration: Dictionary<object, T> _proxyMap = new (new ReferenceEquality()); Then when you create a proxy instance you can store it in the dictionary: object proxy = proxy = ProxyGen.CreateInterfaceProxyWithTarget( ... );
_proxyMap.Add(proxy, T); And pull it out safely: Assert.True(_proxyMap.TryGetValue(proxy, out var tInstance)); I believe the Equals interceptor solution in @stakx's comment is better, but our approach solved our problem as well. |
ProxyGenerator.CreateClassProxyWithTarget returns a proxy instance
p
wherep.Equals(p)
returns false.I can't find any documentation or code to indicate why this happens. We recently updated from 4.4.1 to 5.1.1 and noticed this new behavior/issue with proxy equality. Below is a simple test to demonstrate the error.
Why does
p.Equals(p)
return false?The text was updated successfully, but these errors were encountered: