Skip to content

Fix duplicated methods generated in proxies #2264

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

Merged

Conversation

fredericDelaporte
Copy link
Member

@fredericDelaporte fredericDelaporte commented Nov 3, 2019

Fixes #2085

foreach (var interfaceMethod in interfaces.SelectMany(i => i.GetMethods()))
{
proxiableMethods.Add(interfaceMethod);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could have kept the previous code, just giving the comparer to Distinct. But its contract does not guarantee we will takes the base type methods rather than "duplicated" methods from the interfaces. (Its current implementation will keep the methods from the base type, but we should not rely on this.)
By explicitly adding the base methods to the hashset first, it is guaranteed that this is dups from interfaces which will be ignored.

if (explicitImplementation &&
(typeBuilder.BaseType == typeof(object) ||
#pragma warning disable 618
typeBuilder.BaseType == typeof(ProxyDummy)) &&
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Old dynamic proxy legacy. Not handling this causes its InterfaceWithEqualsGethashcodeTests test to fail.

method.ReturnType,
parameters.ToArray(param => param.ParameterType));
if (explicitImplementation)
methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed | MethodImplAttributes.IL);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied from NHibernateProxyBuilder.ImplementGetLazyInitializer explicit implementation, I do not actually know if it is needed.

/// method which implements it. This implies the base type method has the same signature and there is no
/// explicit implementation of the interface method in the base type.
/// </summary>
private class MethodInfoComparer : IEqualityComparer<MethodInfo>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comparer is just an optimization to generate only one method if the interface method is implemented implicitly. Right?

Copy link
Member Author

@fredericDelaporte fredericDelaporte Nov 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially I wanted to handle it fully in the method using that comparer, but it was too complex.

Yes it is for generating only one method if the interface is implemented implicitly. No it is not an optimization from my viewpoint.

Not doing so, while implementing the base method and the interface method both publicly, is #2085 bug. Granted, the other changes in the method generation is enough to fix it alone, while this change is not enough for explicit implementation cases.

But then, not doing so would trigger again #2052. This bug was re-qualified as just a "possible breaking change" bound to the switch to the static proxy, but if we can avoid that breaking change, that would be better. Otherwise those who read the Id through an implicitly implemented interface will trigger somewhat undue lazy loadings. This really can cause major performance issues.

@fredericDelaporte
Copy link
Member Author

Your change seems to me a good change in principle, but I have not yet thoroughly reviewed it, just to let you know.

@hazzik
Copy link
Member

hazzik commented Nov 6, 2019

Your change seems to me a good change in principle, but I have not yet thoroughly reviewed it, just to let you know.

I've just moved the logic out of the comparer.

@hazzik
Copy link
Member

hazzik commented Nov 6, 2019

Would it be fair to say that the GetProxiableMethods method is doing following: "getting all 'proxiable' methods from a base class plus all interfaces' methods which are not implicitly implemented by the base class"?

@fredericDelaporte
Copy link
Member Author

fredericDelaporte commented Nov 10, 2019

Yes, that is it.
So it could simply be named GetProxyMethods.

@fredericDelaporte
Copy link
Member Author

I've just moved the logic out of the comparer.

Indeed, I agree with the change.

@fredericDelaporte fredericDelaporte added this to the 5.3 milestone Nov 11, 2019
@fredericDelaporte fredericDelaporte merged commit d8931ac into nhibernate:master Nov 11, 2019
@fredericDelaporte fredericDelaporte deleted the FixProxyGeneration branch November 11, 2019 15:39
@bahusoid

This comment has been minimized.

@fredericDelaporte

This comment has been minimized.

@bahusoid

This comment has been minimized.

@bahusoid

This comment has been minimized.

@fredericDelaporte

This comment has been minimized.

@bahusoid

This comment has been minimized.

@fredericDelaporte

This comment has been minimized.

@bahusoid

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Duplicated methods generated in proxies
3 participants