Ejemplo n.º 1
0
        public static unsafe EETypePtr RhGetInterface(EETypePtr ptrEEType, uint index)
        {
            EEType *pEEType = ptrEEType.ToPointer();

            // The convoluted pointer arithmetic into the interface map below (rather than a simply array
            // dereference) is because C# will generate a 64-bit multiply for the lookup by default. This
            // causes us a problem on x86 because it uses a helper that's mapped directly into the CRT via
            // import magic and that technique doesn't work with the way we link this code into the runtime
            // image. Since we don't need a 64-bit multiply here (the classlib is trusted code) we manually
            // perform the calculation.
            EEInterfaceInfo *pInfo = (EEInterfaceInfo *)((byte *)pEEType->InterfaceMap + (index * (uint)sizeof(EEInterfaceInfo)));

            return(new EETypePtr((IntPtr)pInfo->InterfaceType));
        }
Ejemplo n.º 2
0
        static internal unsafe bool ImplementsInterface(EEType *pObjType, EEType *pTargetType)
        {
            Debug.Assert(!pTargetType->IsParameterizedType, "did not expect paramterized type");
            Debug.Assert(pTargetType->IsInterface, "IsInstanceOfInterface called with non-interface EEType");

            // This can happen with generic interface types
            // Debug.Assert(!pTargetType->IsCloned, "cloned interface types are disallowed");

            // canonicalize target type
            if (pTargetType->IsCloned)
            {
                pTargetType = pTargetType->CanonicalEEType;
            }

            int numInterfaces             = pObjType->NumInterfaces;
            EEInterfaceInfo *interfaceMap = pObjType->InterfaceMap;

            for (int i = 0; i < numInterfaces; i++)
            {
                EEType *pInterfaceType = interfaceMap[i].InterfaceType;

                // canonicalize the interface type
                if (pInterfaceType->IsCloned)
                {
                    pInterfaceType = pInterfaceType->CanonicalEEType;
                }

                if (pInterfaceType == pTargetType)
                {
                    return(true);
                }
            }

            // We did not find the interface type in the list of supported interfaces. There's still one
            // chance left: if the target interface is generic and one or more of its type parameters is co or
            // contra variant then the object can still match if it implements a different instantiation of
            // the interface with type compatible generic arguments.
            //
            // An additional edge case occurs because of array covariance. This forces us to treat any generic
            // interfaces implemented by arrays as covariant over their one type parameter.
            bool fArrayCovariance = pObjType->IsArray;

            if (pTargetType->HasGenericVariance || (fArrayCovariance && pTargetType->IsGeneric))
            {
                // Grab details about the instantiation of the target generic interface.
                EETypeRef *      pTargetInstantiation;
                int              targetArity;
                GenericVariance *pTargetVarianceInfo;
                EEType *         pTargetGenericType = InternalCalls.RhGetGenericInstantiation(pTargetType,
                                                                                              &targetArity,
                                                                                              &pTargetInstantiation,
                                                                                              &pTargetVarianceInfo);

                Debug.Assert(pTargetVarianceInfo != null, "did not expect empty variance info");


                for (int i = 0; i < numInterfaces; i++)
                {
                    EEType *pInterfaceType = interfaceMap[i].InterfaceType;

                    // We can ignore interfaces which are not also marked as having generic variance
                    // unless we're dealing with array covariance.
                    if (pInterfaceType->HasGenericVariance || (fArrayCovariance && pInterfaceType->IsGeneric))
                    {
                        // Grab instantiation details for the candidate interface.
                        EETypeRef *      pInterfaceInstantiation;
                        int              interfaceArity;
                        GenericVariance *pInterfaceVarianceInfo;
                        EEType *         pInterfaceGenericType = InternalCalls.RhGetGenericInstantiation(pInterfaceType,
                                                                                                         &interfaceArity,
                                                                                                         &pInterfaceInstantiation,
                                                                                                         &pInterfaceVarianceInfo);

                        Debug.Assert(pInterfaceVarianceInfo != null, "did not expect empty variance info");

                        // If the generic types aren't the same then the types aren't compatible.
                        if (pInterfaceGenericType != pTargetGenericType)
                        {
                            continue;
                        }

                        // The types represent different instantiations of the same generic type. The
                        // arity of both had better be the same.
                        Debug.Assert(targetArity == interfaceArity, "arity mismatch betweeen generic instantiations");

                        // Compare the instantiations to see if they're compatible taking variance into account.
                        if (TypeParametersAreCompatible(targetArity,
                                                        pInterfaceInstantiation,
                                                        pTargetInstantiation,
                                                        pTargetVarianceInfo,
                                                        fArrayCovariance))
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }