Add support for default interface methods in DispatchProxy (dotnet/corefx#34720)
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>
Fri, 15 Feb 2019 10:46:31 +0000 (11:46 +0100)
committerGitHub <noreply@github.com>
Fri, 15 Feb 2019 10:46:31 +0000 (11:46 +0100)
The generated dispatch proxy shouldn't try to override non-virtual or final methods.

This also fixes a pre-existing bug where we would try to override static method on interfaces (while C# can't emit them, the CLR has supported them for ages).

Fixes dotnet/coreclrdotnet/corefx#15646.

Commit migrated from https://github.com/dotnet/corefx/commit/89b67cc789c78ceb65bf996969aba6e30b0679d0

src/libraries/System.Reflection.DispatchProxy/src/System/Reflection/DispatchProxyGenerator.cs

index b643f13d027e5de688555cd83153f52acbd58b9a..6d4ca2c4f49f85f64d0fa12df70b92acc7f69d4c 100644 (file)
@@ -363,6 +363,11 @@ namespace System.Reflection
 
                 foreach (MethodInfo mi in iface.GetRuntimeMethods())
                 {
+                    // Skip regular/non-virtual instance methods, static methods, and methods that cannot be overriden
+                    // ("methods that cannot be overriden" includes default implementation of other interface methods).
+                    if (!mi.IsVirtual || mi.IsFinal)
+                        continue;
+
                     MethodBuilder mdb = AddMethodImpl(mi);
                     PropertyAccessorInfo associatedProperty;
                     if (propertyMap.TryGetValue(mi, out associatedProperty))
@@ -388,6 +393,13 @@ namespace System.Reflection
                 foreach (PropertyInfo pi in iface.GetRuntimeProperties())
                 {
                     PropertyAccessorInfo ai = propertyMap[pi.GetMethod ?? pi.SetMethod];
+
+                    // If we didn't make an overriden accessor above, this was a static property, non-virtual property,
+                    // or a default implementation of a property of a different interface. In any case, we don't need
+                    // to redeclare it.
+                    if (ai.GetMethodBuilder == null && ai.SetMethodBuilder == null)
+                        continue;
+
                     PropertyBuilder pb = _tb.DefineProperty(pi.Name, pi.Attributes, pi.PropertyType, pi.GetIndexParameters().Select(p => p.ParameterType).ToArray());
                     if (ai.GetMethodBuilder != null)
                         pb.SetGetMethod(ai.GetMethodBuilder);
@@ -398,6 +410,13 @@ namespace System.Reflection
                 foreach (EventInfo ei in iface.GetRuntimeEvents())
                 {
                     EventAccessorInfo ai = eventMap[ei.AddMethod ?? ei.RemoveMethod];
+
+                    // If we didn't make an overriden accessor above, this was a static event, non-virtual event,
+                    // or a default implementation of an event of a different interface. In any case, we don't
+                    // need to redeclare it.
+                    if (ai.AddMethodBuilder == null && ai.RemoveMethodBuilder == null && ai.RaiseMethodBuilder == null)
+                        continue;
+
                     EventBuilder eb = _tb.DefineEvent(ei.Name, ei.Attributes, ei.EventHandlerType);
                     if (ai.AddMethodBuilder != null)
                         eb.SetAddOnMethod(ai.AddMethodBuilder);