@@ -32,12 +32,35 @@ public InterfaceMembersOnClassCollector(Type type, bool onlyProxyVirtual, Interf
3232
3333 protected override MetaMethod GetMethodToGenerate ( MethodInfo method , IProxyGenerationHook hook , bool isStandalone )
3434 {
35- if ( onlyProxyVirtual && IsVirtuallyImplementedInterfaceMethod ( method ) )
35+ var methodOnTarget = GetMethodOnTarget ( method ) ;
36+
37+ if ( onlyProxyVirtual )
3638 {
37- return null ;
38- }
39+ // The (somewhat confusingly named) `onlyProxyVirtual` flag may need some explaining.
40+ //
41+ // This collector type is used in two distinct scenarios:
42+ //
43+ // 1. When generating a class proxy for some class `T` which implements interface `I`,
44+ // and `I` is again specified as an additional interface to add to the proxy type.
45+ // In this case, this collector gets invoked for `I` and `onlyProxyVirtual == true`,
46+ // and below logic prevents `I` methods from being implemented a second time when
47+ // the main "target" contributor already took care of them (which happens when they
48+ // are overridable, or more specifically, when they are implicitly implemented and
49+ // marked as `virtual`).
50+ //
51+ // 2. When generating an interface proxy with target for some interface `I` and target
52+ // type `T`. In this case, `onlyProxyVirtual == false`, which forces members of `I`
53+ // to get implemented. Unlike in (1), the target of such proxies will be separate
54+ // objects, so it doesn't matter if & how they implement members of `I` or not;
55+ // those `I` members still need to be implemented on the proxy type regardless.
3956
40- var methodOnTarget = GetMethodOnTarget ( method ) ;
57+ var isVirtuallyImplementedInterfaceMethod = methodOnTarget != null && methodOnTarget . IsFinal == false ;
58+
59+ if ( isVirtuallyImplementedInterfaceMethod )
60+ {
61+ return null ;
62+ }
63+ }
4164
4265 var proxyable = AcceptMethod ( method , onlyProxyVirtual , hook ) ;
4366 return new MetaMethod ( method , methodOnTarget , isStandalone , proxyable , methodOnTarget . IsPrivate == false ) ;
@@ -53,11 +76,5 @@ private MethodInfo GetMethodOnTarget(MethodInfo method)
5376
5477 return map . TargetMethods [ index ] ;
5578 }
56-
57- private bool IsVirtuallyImplementedInterfaceMethod ( MethodInfo method )
58- {
59- var info = GetMethodOnTarget ( method ) ;
60- return info != null && info . IsFinal == false ;
61- }
6279 }
6380}
0 commit comments