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()); }
internal CallInstanceMethodBinder(string name, RuntimeTypeHandle classContext, RuntimeTypeHandle returnType) : base(returnType) { _name = name; _classCtx = classContext.Equals(default(RuntimeTypeHandle)) ? null : Type.GetTypeFromHandle(classContext); }
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); } }
/// <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)); }
/// <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 }
// 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); }
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); }
/// <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)); }
/// <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()); }
/// <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)); }
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)); }
/// <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); }
bool IDynamicInterfaceCastable.IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented) => interfaceType.Equals(typeof(TInterface).TypeHandle);
RuntimeTypeHandle IDynamicInterfaceCastable.GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => interfaceType.Equals(typeof(TInterface).TypeHandle) ? typeof(TImpl).TypeHandle : default;