-
Notifications
You must be signed in to change notification settings - Fork 466
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
"Duplicate element: MetaMethod" for specific combinations of namespace & type names #469
Comments
A possible solution could work by changing code in this location:
roughly as follows: if (Contains(item))
{
item.SwitchToExplicitImplementation();
if (Contains(item))
{
- // there is something *really* wrong going on here
- throw new ProxyGenerationException("Duplicate element: " + item);
+ item.SwitchToFullyQualifiedTypeNameInImplementationName();
}
} ...where that imaginary method would change an implementation method name such as (Even that might theoretically not be sufficient when people do really weird stuff like spreading their identically named types in identically named namespaces over several assemblies, using |
It appears that the Roslyn C# compiler will generally play it safe and include namespace names when explicitly implementing a method. We could follow its lead and apply the following straightforward bug fix in
I think I'll submit a PR including test cases and whatnot shortly. |
@stakx I like your suggested fix to include the namespace, interesting that we weren't doing this before, maybe the old C# compiler just prefixed with type name. I wondered if Roslyn puts long namespaces into the method name too, yep it does. |
Originally reported at nsubstitute/NSubstitute#585, this looks like a bug in DynamicProxy.
Code to reproduce:
The above program triggers the following exception:
As noted in the original issue, namespace and type names matter a lot here. Swapping the namespace names, renaming the namespace
A
toa
, or renaming the interfaceH
toh
, will make the problem go away.Preliminary analysis
The reason why three identically-named types are needed is the same as in Prevent member name collision when proxy implements same generic interface more than twice #285:
M
gets implicitly implemented asM
.M
will get namedI.M
on the proxy type, i.e. DynamicProxy switches to explicit interface implementation to prevent a name collision.M
, DynamicProxy tries the same strategy to prevent a name collision withM
from step (1), which leads to a name collision withI.M
from step (2).The fact that small name differences like upper/lower case makes a difference points at the type sorting that DynamicProxy uses (IIRC to encourage cache hits).
I am not yet sure how these two things interact with one another to provoke failure.
My current guess is that the error will happen iff the
M
method from the interface that isn't named like the two others gets processed first; because that will mean the others will both have to be explicitly named asI.M
.If the types, on the other hand, get sorted such that an
I.M
method get processed first, there won't be a collision as the proxy type ends up with three methodsM
,I.M
, andH.M
./cc @compact-github, @zvirja
The text was updated successfully, but these errors were encountered: