private bool FindMatchingInterfaceSlot(IntPtr moduleHandle, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch)
        {
            uint numTargetImplementations = entryParser.GetUnsigned();

            for (uint j = 0; j < numTargetImplementations; j++)
            {
                uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned());
                MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken);
                RuntimeTypeHandle targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

            #if REFLECTION_EXECUTION_TRACE
                ReflectionExecutionLogger.WriteLine("    Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle));
            #endif

                uint numIfaceImpls = entryParser.GetUnsigned();

                for (uint k = 0; k < numIfaceImpls; k++)
                {
                    RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());

                    uint numIfaceSigs = entryParser.GetUnsigned();

                    if (!openTargetTypeHandle.Equals(implementingTypeHandle))
                    {
                        // Skip over signatures data
                        for (uint l = 0; l < numIfaceSigs; l++)
                            entryParser.GetUnsigned();

                        continue;
                    }

                    for (uint l = 0; l < numIfaceSigs; l++)
                    {
                        RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle);

                        NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetRvaFromIndex(entryParser.GetUnsigned()));
                        IntPtr currentIfaceSigPtr = ifaceSigParser.Reader.OffsetToAddress(ifaceSigParser.Offset);

                        if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(currentIfaceSigPtr, targetTypeInstantiation, null, out currentIfaceTypeHandle, out currentIfaceSigPtr))
                        {
                            Debug.Assert(!currentIfaceTypeHandle.IsNull());

                            if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) ||
                                (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle)))
                            {
            #if REFLECTION_EXECUTION_TRACE
                                ReflectionExecutionLogger.WriteLine("    " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!");
            #endif
                                // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller
                                declaringType = targetTypeHandle;
                                methodNameAndSignature = targetMethodNameAndSignature;
                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }
        public TypeDesc ResolveRuntimeTypeHandle(RuntimeTypeHandle rtth)
        {
            TypeDesc returnedType;

            if (_runtimeTypeHandleResolutionCache.TryGetValue(rtth, out returnedType))
            {
                return(returnedType);
            }

            if (rtth.Equals(CanonType.RuntimeTypeHandle))
            {
                returnedType = CanonType;
            }
            else if (rtth.Equals(UniversalCanonType.RuntimeTypeHandle))
            {
                returnedType = UniversalCanonType;
            }
            else if (RuntimeAugments.IsGenericTypeDefinition(rtth))
            {
                returnedType = TryGetMetadataBasedTypeFromRuntimeTypeHandle_Uncached(rtth);
                if (returnedType == null)
                {
                    unsafe
                    {
                        TypeDesc[] genericParameters = new TypeDesc[rtth.ToEETypePtr()->GenericArgumentCount];
                        for (int i = 0; i < genericParameters.Length; i++)
                        {
                            genericParameters[i] = GetSignatureVariable(i, false);
                        }

                        returnedType = new NoMetadataType(this, rtth, null, new Instantiation(genericParameters), rtth.GetHashCode());
                    }
                }
            }
            else if (RuntimeAugments.IsGenericType(rtth))
            {
                RuntimeTypeHandle   typeDefRuntimeTypeHandle;
                RuntimeTypeHandle[] genericArgRuntimeTypeHandles;
                typeDefRuntimeTypeHandle = RuntimeAugments.GetGenericInstantiation(rtth, out genericArgRuntimeTypeHandles);

                DefType       typeDef     = (DefType)ResolveRuntimeTypeHandle(typeDefRuntimeTypeHandle);
                Instantiation genericArgs = ResolveRuntimeTypeHandles(genericArgRuntimeTypeHandles);
                returnedType = ResolveGenericInstantiation(typeDef, genericArgs);
            }
            else if (RuntimeAugments.IsArrayType(rtth))
            {
                RuntimeTypeHandle elementTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(rtth);
                TypeDesc          elementType       = ResolveRuntimeTypeHandle(elementTypeHandle);
                unsafe
                {
                    if (rtth.ToEETypePtr()->IsSzArray)
                    {
                        returnedType = GetArrayType(elementType);
                    }
                    else
                    {
                        returnedType = GetArrayType(elementType, rtth.ToEETypePtr()->ArrayRank);
                    }
                }
            }
            else if (RuntimeAugments.IsUnmanagedPointerType(rtth))
            {
                RuntimeTypeHandle targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(rtth);
                TypeDesc          targetType       = ResolveRuntimeTypeHandle(targetTypeHandle);
                returnedType = GetPointerType(targetType);
            }
            else if (RuntimeAugments.IsByRefType(rtth))
            {
                RuntimeTypeHandle targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(rtth);
                TypeDesc          targetType       = ResolveRuntimeTypeHandle(targetTypeHandle);
                returnedType = GetByRefType(targetType);
            }
            else
            {
                returnedType = TryGetMetadataBasedTypeFromRuntimeTypeHandle_Uncached(rtth);
                if (returnedType == null)
                {
                    returnedType = new NoMetadataType(this, rtth, null, Instantiation.Empty, rtth.GetHashCode());
                }
            }

            // We either retrieved an existing DefType that is already registered with the runtime
            // or one that is not associated with an MethodTable yet. If it's not associated, associate it.
            if (returnedType.RuntimeTypeHandle.IsNull())
            {
                TypeBuilderState state = returnedType.GetTypeBuilderStateIfExist();
                bool             skipStoringRuntimeTypeHandle = false;

                // If we've already attempted to lookup and failed to retrieve this type handle, we
                // may have already decided to create a new one. In that case, do not attempt to abort
                // that creation process as it may have already begun the process of type creation
                if (state != null && state.AttemptedAndFailedToRetrieveTypeHandle)
                {
                    skipStoringRuntimeTypeHandle = true;
                }

                if (!skipStoringRuntimeTypeHandle)
                {
                    returnedType.SetRuntimeTypeHandleUnsafe(rtth);
                }
            }

            _runtimeTypeHandleResolutionCache.Add(rtth, returnedType);

            return(returnedType.WithDebugName());
        }
예제 #3
0
 internal CallInstanceMethodBinder(string name, RuntimeTypeHandle classContext, RuntimeTypeHandle returnType)
     : base(returnType)
 {
     _name     = name;
     _classCtx = classContext.Equals(default(RuntimeTypeHandle)) ? null : Type.GetTypeFromHandle(classContext);
 }
예제 #4
0
            public static unsafe IntPtr Get(RuntimeTypeHandle constraintType, RuntimeTypeHandle constrainedMethodType, int constrainedMethodSlot, bool directConstrainedCall = false)
            {
                lock (s_nonGenericConstrainedCallDescs)
                {
                    // Get list of constrained call descs associated with a given type
                    LowLevelList <IntPtr> associatedCallDescs;
                    if (!s_nonGenericConstrainedCallDescs.TryGetValue(constraintType, out associatedCallDescs))
                    {
                        associatedCallDescs = new LowLevelList <IntPtr>();
                        s_nonGenericConstrainedCallDescs.Add(constraintType, associatedCallDescs);
                    }

                    // Perform linear scan of associated call descs to see if one matches
                    for (int i = 0; i < associatedCallDescs.Count; i++)
                    {
                        NonGenericConstrainedCallDesc *callDesc = (NonGenericConstrainedCallDesc *)associatedCallDescs[i];

                        Debug.Assert(constraintType.Equals(callDesc->_constraintType));

                        if (callDesc->_constrainedMethodSlot != constrainedMethodSlot)
                        {
                            continue;
                        }

                        if (!callDesc->_constrainedMethodType.Equals(constrainedMethodType))
                        {
                            continue;
                        }

                        // Found matching entry.
                        return(associatedCallDescs[i]);
                    }

                    // Did not find match, allocate a new one and add it to the lookup list
                    IntPtr newCallDescPtr = MemoryHelpers.AllocateMemory(sizeof(NonGenericConstrainedCallDesc));
                    NonGenericConstrainedCallDesc *newCallDesc = (NonGenericConstrainedCallDesc *)newCallDescPtr;
                    newCallDesc->_exactTarget = IntPtr.Zero;
                    if (directConstrainedCall)
                    {
                        newCallDesc->_lookupFunc = RuntimeAugments.GetUniversalTransitionThunk();
                    }
                    else
                    {
                        if (RuntimeAugments.IsValueType(constraintType))
                        {
                            newCallDesc->_lookupFunc = s_resolveCallOnValueTypeFuncPtr;
                        }
                        else
                        {
                            newCallDesc->_lookupFunc = s_resolveCallOnReferenceTypeFuncPtr;
                        }
                    }


                    newCallDesc->_constraintType        = constraintType;
                    newCallDesc->_constrainedMethodSlot = constrainedMethodSlot;
                    newCallDesc->_constrainedMethodType = constrainedMethodType;

                    associatedCallDescs.Add(newCallDescPtr);

                    return(newCallDescPtr);
                }
            }
예제 #5
0
        /// <summary>
        /// Comparing RuntimeTypeHandle with an object's RuntimeTypeHandle, avoiding going through expensive Object.GetType().TypeHandle path
        /// </summary>
        public static bool IsOfType(this object obj, RuntimeTypeHandle handle)
        {
            RuntimeTypeHandle objType = new RuntimeTypeHandle(obj.EETypePtr);

            return(handle.Equals(objType));
        }
예제 #6
0
        /// <summary>
        /// Construct McgModule
        /// </summary>
        public unsafe McgModule(
            int mcgDataModulePriority,
            McgInterfaceData[] interfaceData,
            CCWTemplateData[] ccwTemplateData,
            FixupRuntimeTypeHandle[] supportedInterfaceList,
            McgClassData[] classData,
            McgBoxingData[] boxingData,
            McgAdditionalClassData[] additionalClassData,
            McgCollectionData[] collectionData,
            McgPInvokeDelegateData[] pinvokeDelegateData,
            McgCCWFactoryInfoEntry[] ccwFactories,
            McgStructMarshalData[] structMarshalData,
            McgUnsafeStructFieldOffsetData[] unsafeStructFieldOffsetData,
            McgGenericArgumentMarshalInfo[] genericArgumentMarshalInfo,
            McgHashcodeVerifyEntry[] hashcodeVerifyData)
        {
            m_mcgDataModulePriority      = mcgDataModulePriority;
            m_interfaceData              = interfaceData;
            m_classData                  = classData;
            m_boxingData                 = boxingData;
            m_collectionData             = collectionData;
            m_pinvokeDelegateData        = pinvokeDelegateData;
            m_additionalClassData        = additionalClassData;
            m_ccwFactories               = ccwFactories;
            m_structMarshalData          = structMarshalData;
            m_unsafeStructOffsetData     = unsafeStructFieldOffsetData;
            m_genericArgumentMarshalInfo = genericArgumentMarshalInfo;

            m_ccwTemplateData = ccwTemplateData;

            // Following code is disabled due to lazy static constructor dependency from McgModule which is
            // static eager constructor. Undo this when McgCurrentModule is using ModuleConstructorAttribute
            // -- Today McgCurrentModule cannot use ModuleConstructor attribute. Module constructors are called
            // after ReflectionExecution has been initialized but ReflectionExecution.Initialize requires
            // McgCurrentModule to have already been initialized because the assembly binder needs MCG support
            // for assembly (scope) name enumeration while registering the new module for reflection.
#if EAGER_CTOR_WORKAROUND
            Debug.Assert(m_interfaceTypeInfo != null);
#endif
            if (supportedInterfaceList != null)
            {
                m_supportedInterfaceList = new RuntimeTypeHandle[supportedInterfaceList.Length];
                for (int i = 0; i < supportedInterfaceList.Length; i++)
                {
                    m_supportedInterfaceList[i] = supportedInterfaceList[i].RuntimeTypeHandle;
                }
            }
            else
            {
                m_supportedInterfaceList = null;
            }

            m_hashcodeVerifyData = hashcodeVerifyData;

#if DEBUG
            // Check no duplicate RuntimeTypeHandle in hashtable
            if (m_interfaceData != null)
            {
                System.Collections.Generic.Internal.HashSet <EquatableRuntimeTypeHandle> intfHashSet =
                    new System.Collections.Generic.Internal.HashSet <EquatableRuntimeTypeHandle>(m_interfaceData.Length);
                foreach (McgInterfaceData item in m_interfaceData)
                {
                    RuntimeTypeHandle typeHnd = item.ItfType;
                    if (!typeHnd.Equals(s_DependencyReductionTypeRemovedTypeHandle) && !typeHnd.Equals(default(RuntimeTypeHandle)))
                    {
                        if (intfHashSet.Add(new EquatableRuntimeTypeHandle(typeHnd), typeHnd.GetHashCode()))
                        {
                            Debug.Assert(false, "Duplicate RuntimeTypeHandle found in m_interfaceData");
                        }
                    }
                }
            }

            if (m_classData != null)
            {
                System.Collections.Generic.Internal.HashSet <EquatableRuntimeTypeHandle> classHashSet =
                    new System.Collections.Generic.Internal.HashSet <EquatableRuntimeTypeHandle>(m_classData.Length);
                foreach (McgClassData item in m_classData)
                {
                    RuntimeTypeHandle typeHnd = item.ClassType;
                    if (!typeHnd.Equals(s_DependencyReductionTypeRemovedTypeHandle) && !typeHnd.Equals(default(RuntimeTypeHandle)))
                    {
                        if (classHashSet.Add(new EquatableRuntimeTypeHandle(typeHnd), typeHnd.GetHashCode()))
                        {
                            Debug.Assert(false, "Duplicate RuntimeTypeHandle found in m_classData");
                        }
                    }
                }
            }

            Debug.Assert(this.VerifyHashCodes());
#endif
        }
예제 #7
0
 // This helper helps reduce the temptation to write "h == default(RuntimeTypeHandle)" which causes boxing.
 public static bool IsNull(this RuntimeTypeHandle h)
 {
     return(h.Equals(default(RuntimeTypeHandle)));
 }
        private bool CompareTypeSigWithType(ref NativeParser parser, IntPtr moduleHandle, Handle typeHandle)
        {
            while (typeHandle.HandleType == HandleType.TypeSpecification)
            {
                typeHandle = typeHandle
                             .ToTypeSpecificationHandle(_metadataReader)
                             .GetTypeSpecification(_metadataReader)
                             .Signature;
            }

            // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader
            // expects to read it in.
            uint startOffset = parser.Offset;

            uint data;
            var  typeSignatureKind = parser.GetTypeSignatureKind(out data);

            switch (typeSignatureKind)
            {
            case TypeSignatureKind.Lookback:
            {
                NativeParser lookbackParser = parser.GetLookbackParser(data);
                return(CompareTypeSigWithType(ref lookbackParser, moduleHandle, typeHandle));
            }

            case TypeSignatureKind.Modifier:
            {
                // Ensure the modifier kind (vector, pointer, byref) is the same
                TypeModifierKind modifierKind = (TypeModifierKind)data;
                switch (modifierKind)
                {
                case TypeModifierKind.Array:
                    if (typeHandle.HandleType == HandleType.SZArraySignature)
                    {
                        return(CompareTypeSigWithType(ref parser, moduleHandle, typeHandle
                                                      .ToSZArraySignatureHandle(_metadataReader)
                                                      .GetSZArraySignature(_metadataReader)
                                                      .ElementType));
                    }
                    return(false);

                case TypeModifierKind.ByRef:
                    if (typeHandle.HandleType == HandleType.ByReferenceSignature)
                    {
                        return(CompareTypeSigWithType(ref parser, moduleHandle, typeHandle
                                                      .ToByReferenceSignatureHandle(_metadataReader)
                                                      .GetByReferenceSignature(_metadataReader)
                                                      .Type));
                    }
                    return(false);

                case TypeModifierKind.Pointer:
                    if (typeHandle.HandleType == HandleType.PointerSignature)
                    {
                        return(CompareTypeSigWithType(ref parser, moduleHandle, typeHandle
                                                      .ToPointerSignatureHandle(_metadataReader)
                                                      .GetPointerSignature(_metadataReader)
                                                      .Type));
                    }
                    return(false);

                default:
                    Debug.Assert(null == "invalid type modifier kind");
                    return(false);
                }
            }

            case TypeSignatureKind.Variable:
            {
                bool isMethodVar = (data & 0x1) == 1;
                uint index       = data >> 1;

                if (isMethodVar)
                {
                    if (typeHandle.HandleType == HandleType.MethodTypeVariableSignature)
                    {
                        return(index == typeHandle
                               .ToMethodTypeVariableSignatureHandle(_metadataReader)
                               .GetMethodTypeVariableSignature(_metadataReader)
                               .Number);
                    }
                }
                else
                {
                    if (typeHandle.HandleType == HandleType.TypeVariableSignature)
                    {
                        return(index == typeHandle
                               .ToTypeVariableSignatureHandle(_metadataReader)
                               .GetTypeVariableSignature(_metadataReader)
                               .Number);
                    }
                }

                return(false);
            }

            case TypeSignatureKind.MultiDimArray:
            {
                if (typeHandle.HandleType != HandleType.ArraySignature)
                {
                    return(false);
                }

                ArraySignature sig = typeHandle
                                     .ToArraySignatureHandle(_metadataReader)
                                     .GetArraySignature(_metadataReader);

                if (data != sig.Rank)
                {
                    return(false);
                }

                if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.ElementType))
                {
                    return(false);
                }

                uint boundCount1 = parser.GetUnsigned();
                for (uint i = 0; i < boundCount1; i++)
                {
                    parser.GetUnsigned();
                }

                uint lowerBoundCount1 = parser.GetUnsigned();

                for (uint i = 0; i < lowerBoundCount1; i++)
                {
                    parser.GetUnsigned();
                }
                break;
            }

            case TypeSignatureKind.FunctionPointer:
            {
                // callingConvention is in data
                uint argCount1 = parser.GetUnsigned();

                for (uint i = 0; i < argCount1; i++)
                {
                    if (!CompareTypeSigWithType(ref parser, moduleHandle, typeHandle))
                    {
                        return(false);
                    }
                }
                return(false);
            }

            case TypeSignatureKind.Instantiation:
            {
                if (typeHandle.HandleType != HandleType.TypeInstantiationSignature)
                {
                    return(false);
                }

                TypeInstantiationSignature sig = typeHandle
                                                 .ToTypeInstantiationSignatureHandle(_metadataReader)
                                                 .GetTypeInstantiationSignature(_metadataReader);

                if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.GenericType))
                {
                    return(false);
                }

                uint genericArgIndex = 0;
                foreach (Handle genericArgumentTypeHandle in sig.GenericTypeArguments)
                {
                    if (genericArgIndex >= data)
                    {
                        // The metadata generic has more parameters than the native layour
                        return(false);
                    }
                    if (!CompareTypeSigWithType(ref parser, moduleHandle, genericArgumentTypeHandle))
                    {
                        return(false);
                    }
                    genericArgIndex++;
                }
                // Make sure all generic parameters have been matched
                return(genericArgIndex == data);
            }

            case TypeSignatureKind.External:
            {
                RuntimeTypeHandle type2;
                switch (typeHandle.HandleType)
                {
                case HandleType.TypeDefinition:
                    if (!TypeLoaderEnvironment.Instance.TryGetNamedTypeForMetadata(
                            _metadataReader, typeHandle.ToTypeDefinitionHandle(_metadataReader), out type2))
                    {
                        return(false);
                    }
                    break;

                case HandleType.TypeReference:
                    if (!TypeLoaderEnvironment.TryResolveNamedTypeForTypeReference(
                            _metadataReader, typeHandle.ToTypeReferenceHandle(_metadataReader), out type2))
                    {
                        return(false);
                    }
                    break;

                default:
                    return(false);
                }

                RuntimeTypeHandle type1 = SigParsing.GetTypeFromNativeLayoutSignature(ref parser, moduleHandle, startOffset);
                return(type1.Equals(type2));
            }

            default:
                return(false);
            }
            return(true);
        }
예제 #9
0
        private bool CompareTypeSigs(ref NativeParser parser1, NativeFormatModuleInfo moduleHandle1, ref NativeParser parser2, NativeFormatModuleInfo moduleHandle2)
        {
            // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader
            // expects to read it in.
            uint data1;
            uint startOffset1       = parser1.Offset;
            var  typeSignatureKind1 = parser1.GetTypeSignatureKind(out data1);

            // If the parser is at a lookback type, get a new parser for it and recurse.
            // Since we haven't read the element type of parser2 yet, we just pass it in unchanged
            if (typeSignatureKind1 == TypeSignatureKind.Lookback)
            {
                NativeParser lookbackParser1 = parser1.GetLookbackParser(data1);
                return(CompareTypeSigs(ref lookbackParser1, moduleHandle1, ref parser2, moduleHandle2));
            }

            uint data2;
            uint startOffset2       = parser2.Offset;
            var  typeSignatureKind2 = parser2.GetTypeSignatureKind(out data2);

            // If parser2 is a lookback type, we need to rewind parser1 to its startOffset1
            // before recursing.
            if (typeSignatureKind2 == TypeSignatureKind.Lookback)
            {
                NativeParser lookbackParser2 = parser2.GetLookbackParser(data2);
                parser1 = new NativeParser(parser1.Reader, startOffset1);
                return(CompareTypeSigs(ref parser1, moduleHandle1, ref lookbackParser2, moduleHandle2));
            }

            if (typeSignatureKind1 != typeSignatureKind2)
            {
                return(false);
            }

            switch (typeSignatureKind1)
            {
            case TypeSignatureKind.Lookback:
            {
                //  Recursion above better have removed all lookbacks
                Debug.Assert(false, "Unexpected lookback type");
                return(false);
            }

            case TypeSignatureKind.Modifier:
            {
                // Ensure the modifier kind (vector, pointer, byref) is the same
                if (data1 != data2)
                {
                    return(false);
                }
                return(CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2));
            }

            case TypeSignatureKind.Variable:
            {
                // variable index is in data
                if (data1 != data2)
                {
                    return(false);
                }
                break;
            }

            case TypeSignatureKind.MultiDimArray:
            {
                // rank is in data
                if (data1 != data2)
                {
                    return(false);
                }

                if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2))
                {
                    return(false);
                }

                uint boundCount1 = parser1.GetUnsigned();
                uint boundCount2 = parser2.GetUnsigned();
                if (boundCount1 != boundCount2)
                {
                    return(false);
                }

                for (uint i = 0; i < boundCount1; i++)
                {
                    if (parser1.GetUnsigned() != parser2.GetUnsigned())
                    {
                        return(false);
                    }
                }

                uint lowerBoundCount1 = parser1.GetUnsigned();
                uint lowerBoundCount2 = parser2.GetUnsigned();
                if (lowerBoundCount1 != lowerBoundCount2)
                {
                    return(false);
                }

                for (uint i = 0; i < lowerBoundCount1; i++)
                {
                    if (parser1.GetUnsigned() != parser2.GetUnsigned())
                    {
                        return(false);
                    }
                }
                break;
            }

            case TypeSignatureKind.FunctionPointer:
            {
                // callingConvention is in data
                if (data1 != data2)
                {
                    return(false);
                }
                uint argCount1 = parser1.GetUnsigned();
                uint argCount2 = parser2.GetUnsigned();
                if (argCount1 != argCount2)
                {
                    return(false);
                }
                for (uint i = 0; i < argCount1; i++)
                {
                    if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2))
                    {
                        return(false);
                    }
                }
                break;
            }

            case TypeSignatureKind.Instantiation:
            {
                // Type parameter count is in data
                if (data1 != data2)
                {
                    return(false);
                }

                if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2))
                {
                    return(false);
                }

                for (uint i = 0; i < data1; i++)
                {
                    if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2))
                    {
                        return(false);
                    }
                }
                break;
            }

            case TypeSignatureKind.External:
            {
                RuntimeTypeHandle typeHandle1 = GetExternalTypeHandle(moduleHandle1, data1);
                RuntimeTypeHandle typeHandle2 = GetExternalTypeHandle(moduleHandle2, data2);
                if (!typeHandle1.Equals(typeHandle2))
                {
                    return(false);
                }

                break;
            }

            default:
                return(false);
            }
            return(true);
        }
예제 #10
0
        /// <summary>
        /// Convert a value to its nullable equivalent.
        /// </summary>
        /// <param name="value">The value to convert.</param>
        /// <param name="underlyingType">The type to make nullable.</param>
        /// <returns>The value cast to a nullable type.</returns>
        private static object AsNullable(object value, Type underlyingType)
        {
            RuntimeTypeHandle underlyingHandle = underlyingType.TypeHandle;

            if (underlyingHandle.Equals(typeof(bool).TypeHandle))
            {
                return((bool?)value);
            }
            else if (underlyingHandle.Equals(typeof(int).TypeHandle))
            {
                return((int?)value);
            }
            else if (underlyingHandle.Equals(typeof(uint).TypeHandle))
            {
                return((uint?)value);
            }
            else if (underlyingHandle.Equals(typeof(sbyte).TypeHandle))
            {
                return((sbyte?)value);
            }
            else if (underlyingHandle.Equals(typeof(byte).TypeHandle))
            {
                return((byte?)value);
            }
            else if (underlyingHandle.Equals(typeof(short).TypeHandle))
            {
                return((short?)value);
            }
            else if (underlyingHandle.Equals(typeof(ushort).TypeHandle))
            {
                return((ushort?)value);
            }
            else if (underlyingHandle.Equals(typeof(long).TypeHandle))
            {
                return((long?)value);
            }
            else if (underlyingHandle.Equals(typeof(ulong).TypeHandle))
            {
                return((ulong?)value);
            }
            else if (underlyingHandle.Equals(typeof(double).TypeHandle))
            {
                return((double?)value);
            }
            else if (underlyingHandle.Equals(typeof(float).TypeHandle))
            {
                return((float?)value);
            }
            else if (underlyingHandle.Equals(typeof(Decimal).TypeHandle))
            {
                return((Decimal?)value);
            }
            else if (underlyingHandle.Equals(typeof(char).TypeHandle))
            {
                return((char?)value);
            }
            else if (underlyingHandle.Equals(typeof(DateTime).TypeHandle))
            {
                return((DateTime?)value);
            }

            // If all else fails, default to ChangeType
            return(Convert.ChangeType(
                       value,
                       typeof(Nullable <>).MakeGenericType(underlyingType),
                       CultureInfo.InvariantCulture));
        }
예제 #11
0
        /// <summary>
        /// Convert a value into an OData literal.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The corresponding OData literal.</returns>
        public static string ToODataConstant(object value)
        {
            if (value == null)
            {
                return("null");
            }

            // Special case a few primtive types
            RuntimeTypeHandle handle = value.GetType().TypeHandle;

            if (handle.Equals(typeof(bool).TypeHandle))
            {
                // Make sure booleans are lower case
                return(((bool)value).ToString().ToLower());
            }
            else if (handle.Equals(typeof(Byte).TypeHandle))
            {
                // Format bytes as hex pairs
                return(((byte)value).ToString("X2", CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(long).TypeHandle))
            {
                return(value.ToString() + "L");
            }
            else if (handle.Equals(typeof(float).TypeHandle))
            {
                return(value.ToString() + "f");
            }
            else if (handle.Equals(typeof(Decimal).TypeHandle))
            {
                return(value.ToString() + "M");
            }
            else if (handle.Equals(typeof(string).TypeHandle))
            {
                // Escape the string constant by: (1) replacing single quotes with a
                // pair of single quotes, and (2) Uri escaping with percent encoding
                string text        = value as string ?? string.Empty;
                string textEscaped = Uri.EscapeDataString(text.Replace("'", "''"));
                return(string.Format(CultureInfo.InvariantCulture, "'{0}'", textEscaped));
            }
            else if (handle.Equals(typeof(char).TypeHandle))
            {
                // Escape the char constant by: (1) replacing a single quote with a
                // pair of single quotes, and (2) Uri escaping with percent encoding
                char   ch          = (char)value;
                string charEscaped = Uri.EscapeDataString(ch == '\'' ? "''" : ch.ToString());
                return(string.Format(CultureInfo.InvariantCulture, "'{0}'", charEscaped));
            }
            else if (handle.Equals(typeof(DateTime).TypeHandle))
            {
                // Format dates in the official OData format
                return(string.Format(
                           CultureInfo.InvariantCulture,
                           "datetime'{0}'",
                           ((DateTime)value).ToRoundtripDateString()));
            }
            else if (handle.Equals(typeof(DateTimeOffset).TypeHandle))
            {
                // Format dates in the official OData format (note: the server
                // doesn't recgonize datetimeoffset'...', so we'll just convert
                // to a UTC date.
                return(string.Format(
                           CultureInfo.InvariantCulture,
                           "datetime'{0}'",
                           ((DateTimeOffset)value).DateTime.ToRoundtripDateString()));
            }
            else if (handle.Equals(typeof(Guid).TypeHandle))
            {
                // GUIDs are in registry format without the { }s
                Guid guid = (Guid)value;
                return(string.Format(
                           CultureInfo.InvariantCulture,
                           "guid'{0}'",
                           guid.ToString().TrimStart('{').TrimEnd('}')));
            }

            // We'll just ToString everything else
            return(value.ToString());
        }
예제 #12
0
        /// <summary>
        /// Change the value of an object from one type to another.
        /// </summary>
        /// <param name="value">The value to change.</param>
        /// <param name="desiredType">The desired type.</param>
        /// <returns>The converted value.</returns>
        public static object ChangeType(object value, Type desiredType)
        {
            Debug.Assert(desiredType != null, "desiredType cannot be null.");

            // Ignore null values because there's nothing we need to convert
            if (value == null)
            {
                return(null);
            }

            // If the desired type is nullable, convert the value (which we've
            // already verified isn't null) into the underlying type and then
            // convert that result into the nullable type.
            Type underlyingType = Nullable.GetUnderlyingType(desiredType);

            if (underlyingType != null)
            {
                value = ChangeType(value, underlyingType);
                return(AsNullable(value, underlyingType));
            }

            // Try the primitive types (note that Convert.ToFoo will allow us
            // to cast and truncate precision in a lot of cases where the
            // Convert.ChangeType will throw an InvalidCastException).
            RuntimeTypeHandle handle = desiredType.TypeHandle;

            if (handle.Equals(typeof(bool).TypeHandle))
            {
                return(Convert.ToBoolean(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(int).TypeHandle))
            {
                return(Convert.ToInt32(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(uint).TypeHandle))
            {
                return(Convert.ToUInt32(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(sbyte).TypeHandle))
            {
                return(Convert.ToSByte(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(byte).TypeHandle))
            {
                return(Convert.ToByte(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(short).TypeHandle))
            {
                return(Convert.ToInt16(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(ushort).TypeHandle))
            {
                return(Convert.ToUInt16(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(long).TypeHandle))
            {
                return(Convert.ToInt64(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(ulong).TypeHandle))
            {
                return(Convert.ToUInt64(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(double).TypeHandle))
            {
                return(Convert.ToDouble(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(float).TypeHandle))
            {
                return(Convert.ToSingle(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(Decimal).TypeHandle))
            {
                return(Convert.ToDecimal(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(char).TypeHandle))
            {
                return(Convert.ToChar(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(string).TypeHandle))
            {
                return(Convert.ToString(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(DateTime).TypeHandle))
            {
                return(Convert.ToDateTime(value, CultureInfo.InvariantCulture));
            }
            else if (handle.Equals(typeof(DateTimeOffset).TypeHandle))
            {
                return(new DateTimeOffset(Convert.ToDateTime(value, CultureInfo.InvariantCulture)));
            }

            // If all else fails, default to ChangeType
            return(Convert.ChangeType(value, desiredType, CultureInfo.InvariantCulture));
        }
예제 #13
0
        internal unsafe static IntPtr ObjectToComInterfaceInternal(Object obj, RuntimeTypeHandle typeHnd)
        {
            if (obj == null)
            {
                return(default(IntPtr));
            }

#if ENABLE_WINRT
            //
            // Try boxing if this is a WinRT object
            //
            if (typeHnd.Equals(InternalTypes.IInspectable))
            {
                object unboxed = McgMarshal.BoxIfBoxable(obj);

                //
                // Marshal ReferenceImpl<T> to WinRT as IInspectable
                //
                if (unboxed != null)
                {
                    obj = unboxed;
                }
                else
                {
                    //
                    // Anything that can be casted to object[] will be boxed as object[]
                    //
                    object[] objArray = obj as object[];
                    if (objArray != null)
                    {
                        unboxed = McgMarshal.BoxIfBoxable(obj, typeof(object[]).TypeHandle);
                        if (unboxed != null)
                        {
                            obj = unboxed;
                        }
                    }
                }
            }
#endif //ENABLE_WINRT

            //
            // If this is a RCW, and the RCW is not a base class (managed class deriving from RCW class),
            // QI on the RCW
            //
            __ComObject comObject = obj as __ComObject;

            if (comObject != null && !comObject.ExtendsComObject)
            {
                IntPtr pComPtr = comObject.QueryInterface_NoAddRef_Internal(typeHnd, /* cacheOnly= */ false, /* throwOnQueryInterfaceFailure= */ false);
                if (pComPtr == default(IntPtr))
                {
                    return(default(IntPtr));
                }

                McgMarshal.ComAddRef(pComPtr);
                GC.KeepAlive(comObject); // make sure we don't collect the object before adding a refcount.

                return(pComPtr);
            }

            //
            // Otherwise, go down the CCW code path
            //
            return(ManagedObjectToComInterface(obj, typeHnd));
        }
예제 #14
0
        /// <summary>
        /// Returns the existing RCW or create a new RCW from the COM interface pointer
        /// NOTE: This does unboxing unless CreateComObjectFlags.SkipTypeResolutionAndUnboxing is specified
        /// </summary>
        /// <param name="expectedContext">
        /// The current context of this thread. If it is passed and is not Default, we'll check whether the
        /// returned RCW from cache matches this expected context. If it is not a match (from a different
        /// context, and is not free threaded), we'll go ahead ignoring the cached entry, and create a new
        /// RCW instead - which will always end up in the current context
        /// We'll skip the check if current == ContextCookie.Default.
        /// </param>
        internal static object ComInterfaceToComObjectInternal(
            IntPtr pComItf,
            IntPtr pComIdentityIUnknown,
            RuntimeTypeHandle interfaceType,
            RuntimeTypeHandle classTypeInSignature,
            ContextCookie expectedContext,
            CreateComObjectFlags flags
            )
        {
            string className;
            object obj = ComInterfaceToComObjectInternal_NoCache(
                pComItf,
                pComIdentityIUnknown,
                interfaceType,
                classTypeInSignature,
                expectedContext,
                flags,
                out className
                );

            //
            // The assumption here is that if the classInfoInSignature is null and interfaceTypeInfo
            // is either IUnknow and IInspectable we need to try unboxing.
            //
            bool doUnboxingCheck =
                (flags & CreateComObjectFlags.SkipTypeResolutionAndUnboxing) == 0 &&
                obj != null &&
                classTypeInSignature.IsNull() &&
                (interfaceType.Equals(InternalTypes.IUnknown) ||
                 interfaceType.IsIInspectable());

            if (doUnboxingCheck)
            {
                //
                // Try unboxing
                // Even though this might just be a IUnknown * from the signature, we still attempt to unbox
                // if it implements IInspectable
                //
                // @TODO - We might need to optimize this by pre-checking the names to see if they
                // potentially represents a boxed type, but for now let's keep it simple and I also don't
                // want to replicate the knowledge here
                // @TODO2- We probably should skip the creating the COM object in the first place.
                //
                // NOTE: the RCW here could be a cached one (for a brief time if GC doesn't kick in. as there
                // is nothing to hold the RCW alive for IReference<T> RCWs), so this could save us a RCW
                // creation cost potentially. Desktop CLR doesn't do this. But we also paying for unnecessary
                // cache management cost, and it is difficult to say which way is better without proper
                // measuring
                //
                object unboxedObj = McgMarshal.UnboxIfBoxed(obj, className);
                if (unboxedObj != null)
                {
                    return(unboxedObj);
                }
            }

            //
            // In order for variance to work, we save the incoming interface pointer as specified in the
            // signature into the cache, so that we know this RCW does support this interface and variance
            // can take advantage of that later
            // NOTE: In some cases, native might pass a WinRT object as a 'compatible' interface, for example,
            // pass IVector<IFoo> as IVector<Object> because they are 'compatible', but QI for IVector<object>
            // won't succeed. In this case, we'll just believe it implements IVector<Object> as in the
            // signature while the underlying interface pointer is actually IVector<IFoo>
            //
            __ComObject comObject = obj as __ComObject;

            if (comObject != null)
            {
                McgMarshal.ComAddRef(pComItf);

                try
                {
                    comObject.InsertIntoCache(interfaceType, ContextCookie.Current, ref pComItf, true);
                }
                finally
                {
                    //
                    // Only release when a exception is thrown or we didn't 'swallow' the ref count by
                    // inserting it into the cache
                    //
                    McgMarshal.ComSafeRelease(pComItf);
                }
            }

            return(obj);
        }
예제 #15
0
 bool IDynamicInterfaceCastable.IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
 => interfaceType.Equals(typeof(TInterface).TypeHandle);
예제 #16
0
 RuntimeTypeHandle IDynamicInterfaceCastable.GetInterfaceImplementation(RuntimeTypeHandle interfaceType)
 => interfaceType.Equals(typeof(TInterface).TypeHandle) ? typeof(TImpl).TypeHandle : default;