예제 #1
0
        private static DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, MetadataType currentType, out MethodDesc impl)
        {
            TypeDesc     interfaceMethodOwningType = interfaceMethod.OwningType;
            MetadataType mostSpecificInterface     = null;
            bool         diamondCase = false;

            impl = null;

            MethodDesc interfaceMethodDefinition = interfaceMethod.GetMethodDefinition();

            DefType[] consideredInterfaces;
            if (!currentType.IsInterface)
            {
                // If this is not an interface, only things on the interface list could provide
                // default implementations.
                consideredInterfaces = currentType.RuntimeInterfaces;
            }
            else
            {
                // If we're asking about an interface, include the interface in the list.
                consideredInterfaces = new DefType[currentType.RuntimeInterfaces.Length + 1];
                Array.Copy(currentType.RuntimeInterfaces, consideredInterfaces, currentType.RuntimeInterfaces.Length);
                consideredInterfaces[consideredInterfaces.Length - 1] = (DefType)currentType.InstantiateAsOpen();
            }

            foreach (MetadataType runtimeInterface in consideredInterfaces)
            {
                if (runtimeInterface == interfaceMethodOwningType)
                {
                    // Also consider the default interface method implementation on the interface itself
                    // if we don't have anything else yet
                    if (mostSpecificInterface == null && !interfaceMethod.IsAbstract)
                    {
                        mostSpecificInterface = runtimeInterface;
                        impl = interfaceMethodDefinition;
                    }
                }
                else if (Array.IndexOf(runtimeInterface.RuntimeInterfaces, interfaceMethodOwningType) != -1)
                {
                    // This interface might provide a default implementation
                    MethodImplRecord[] possibleImpls = runtimeInterface.FindMethodsImplWithMatchingDeclName(interfaceMethod.Name);
                    if (possibleImpls != null)
                    {
                        foreach (MethodImplRecord implRecord in possibleImpls)
                        {
                            if (implRecord.Decl == interfaceMethodDefinition)
                            {
                                // This interface provides a default implementation.
                                // Is it also most specific?
                                if (mostSpecificInterface == null || Array.IndexOf(runtimeInterface.RuntimeInterfaces, mostSpecificInterface) != -1)
                                {
                                    mostSpecificInterface = runtimeInterface;
                                    impl        = implRecord.Body;
                                    diamondCase = false;
                                }
                                else if (Array.IndexOf(mostSpecificInterface.RuntimeInterfaces, runtimeInterface) == -1)
                                {
                                    diamondCase = true;
                                }

                                break;
                            }
                        }
                    }
                }
            }

            if (diamondCase)
            {
                impl = null;
                return(DefaultInterfaceMethodResolution.Diamond);
            }
            else if (impl == null)
            {
                return(DefaultInterfaceMethodResolution.None);
            }
            else if (impl.IsAbstract)
            {
                impl = null;
                return(DefaultInterfaceMethodResolution.Reabstraction);
            }

            if (interfaceMethod != interfaceMethodDefinition)
            {
                impl = impl.MakeInstantiatedMethod(interfaceMethod.Instantiation);
            }

            return(DefaultInterfaceMethodResolution.DefaultImplementation);
        }