public override string ToString() { if (_cachedToString != null) { return(_cachedToString); } StringBuilder sb = new StringBuilder(); if (!_genericTypeDefinition.IsNull()) { sb.Append(_genericTypeDefinition.LowLevelToString()); } else if (!RuntimeTypeHandle.IsNull()) { sb.Append(RuntimeTypeHandle.LowLevelToString()); } if (!Instantiation.IsNull) { for (int i = 0; i < Instantiation.Length; i++) { sb.Append(i == 0 ? "[" : ", "); sb.Append(Instantiation[i].ToString()); } if (Instantiation.Length > 0) { sb.Append("]"); } } _cachedToString = sb.ToString(); return(_cachedToString); }
public bool IsCanonicallyEquivalent(RuntimeTypeHandle other) { if (_defType != null) { TypeDesc typeToFindAsCanon = _defType.ConvertToCanonForm(_canonKind); TypeDesc otherTypeAsTypeDesc = _defType.Context.ResolveRuntimeTypeHandle(other); TypeDesc otherTypeAsCanon = otherTypeAsTypeDesc.ConvertToCanonForm(_canonKind); return(typeToFindAsCanon == otherTypeAsCanon); } if (!_genericDefinition.IsNull()) { if (RuntimeAugments.IsGenericType(other)) { RuntimeTypeHandle otherGenericDefinition; RuntimeTypeHandle[] otherGenericArgs; otherGenericDefinition = RuntimeAugments.GetGenericInstantiation(other, out otherGenericArgs); return(_genericDefinition.Equals(otherGenericDefinition) && TypeLoaderEnvironment.Instance.CanInstantiationsShareCode(_genericArgs, otherGenericArgs, _canonKind)); } else { return(false); } } else { return(_typeToFind.Equals(other)); } }
private static __ComObject CreateComObjectInternal(RuntimeTypeHandle classType, IntPtr pComItf) { Debug.Assert(!classType.IsNull()); if (classType.Equals(McgModule.s_DependencyReductionTypeRemovedTypeHandle)) { // We should filter out the strongly typed RCW in TryGetClassInfoFromName step #if !RHTESTCL Environment.FailFast(McgTypeHelpers.GetDiagnosticMessageForMissingType(classType)); #else Environment.FailFast("We should never see strongly typed RCW discarded here"); #endif } //Note that this doesn't run the constructor in RH but probably do in your reflection based implementation. //If this were a real RCW, you would actually 'new' the RCW which is wrong. Fortunately in CoreCLR we don't have //this scenario so we are OK, but we should figure out a way to fix this by having a runtime API. object newClass = InteropExtensions.RuntimeNewObject(classType); Debug.Assert(newClass is __ComObject); __ComObject newObj = InteropExtensions.UncheckedCast <__ComObject>(newClass); IntPtr pfnCtor = AddrOfIntrinsics.AddrOf <AddrOfIntrinsics.AddrOfAttachingCtor>(__ComObject.AttachingCtor); CalliIntrinsics.Call <int>(pfnCtor, newObj, pComItf, classType); return(newObj); }
private static RuntimeTypeHandle GetRuntimeTypeHandleIfAny(RuntimeTypeInfo elementType, bool multiDim, int rank) { Debug.Assert(multiDim || rank == 1); RuntimeTypeHandle elementTypeHandle = elementType.InternalTypeHandleIfAvailable; if (elementTypeHandle.IsNull()) { return(default(RuntimeTypeHandle)); } RuntimeTypeHandle typeHandle; if (!multiDim) { if (!ReflectionCoreExecution.ExecutionEnvironment.TryGetArrayTypeForElementType(elementTypeHandle, out typeHandle)) { return(default(RuntimeTypeHandle)); } } else { if (!ReflectionCoreExecution.ExecutionEnvironment.TryGetMultiDimArrayTypeForElementType(elementTypeHandle, rank, out typeHandle)) { return(default(RuntimeTypeHandle)); } } return(typeHandle); }
/// <summary> /// Setter for RuntimeTypeHandle. Seperate from normal property as all uses should be done with great care. /// Must not be set with partially constructed type handles /// </summary> public void SetRuntimeTypeHandleUnsafe(RuntimeTypeHandle runtimeTypeHandle) { Debug.Assert(!runtimeTypeHandle.IsNull()); Debug.Assert(_runtimeTypeHandle.IsNull() || runtimeTypeHandle.Equals(_runtimeTypeHandle)); Debug.Assert(runtimeTypeHandle.GetHashCode() == GetHashCode()); _runtimeTypeHandle = runtimeTypeHandle; }
private void GetTypeNameHelper(out string name, out string nsName, out string assemblyName) { TypeReferenceHandle typeRefHandle; QTypeDefinition qTypeDefinition; MetadataReader reader; RuntimeTypeHandle genericDefinitionHandle = GetTypeDefinition().GetRuntimeTypeHandle(); Debug.Assert(!genericDefinitionHandle.IsNull()); string enclosingDummy; // Try to get the name from metadata if (TypeLoaderEnvironment.Instance.TryGetMetadataForNamedType(genericDefinitionHandle, out qTypeDefinition)) { TypeDefinitionHandle typeDefHandle = qTypeDefinition.NativeFormatHandle; typeDefHandle.GetFullName(qTypeDefinition.NativeFormatReader, out name, out enclosingDummy, out nsName); assemblyName = typeDefHandle.GetContainingModuleName(qTypeDefinition.NativeFormatReader); } // Try to get the name from diagnostic metadata else if (TypeLoaderEnvironment.TryGetTypeReferenceForNamedType(genericDefinitionHandle, out reader, out typeRefHandle)) { typeRefHandle.GetFullName(reader, out name, out enclosingDummy, out nsName); assemblyName = typeRefHandle.GetContainingModuleName(reader); } else { name = genericDefinitionHandle.LowLevelToStringRawEETypeAddress(); nsName = ""; assemblyName = "?"; } }
internal HandleBasedGenericMethodLookup(RuntimeTypeHandle declaringType, MethodNameAndSignature nameAndSignature, RuntimeTypeHandle[] genericMethodArgumentHandles) : base(null) { Debug.Assert(!declaringType.IsNull() && nameAndSignature != null && genericMethodArgumentHandles != null); _declaringType = declaringType; _nameAndSignature = nameAndSignature; _genericMethodArgumentHandles = genericMethodArgumentHandles; }
internal static RuntimePointerTypeInfo GetPointerTypeInfo(RuntimeTypeInfo elementType, RuntimeTypeHandle precomputedTypeHandle) { RuntimeTypeHandle typeHandle = precomputedTypeHandle.IsNull() ? GetRuntimeTypeHandleIfAny(elementType) : precomputedTypeHandle; RuntimePointerTypeInfo type = PointerTypeTable.Table.GetOrAdd(new UnificationKey(elementType, typeHandle)); type.EstablishDebugName(); return(type); }
internal static RuntimeConstructedGenericTypeInfo GetRuntimeConstructedGenericTypeInfo(RuntimeTypeInfo genericTypeDefinition, RuntimeTypeInfo[] genericTypeArguments, RuntimeTypeHandle precomputedTypeHandle) { RuntimeTypeHandle typeHandle = precomputedTypeHandle.IsNull() ? GetRuntimeTypeHandleIfAny(genericTypeDefinition, genericTypeArguments) : precomputedTypeHandle; UnificationKey key = new UnificationKey(genericTypeDefinition, genericTypeArguments, typeHandle); RuntimeConstructedGenericTypeInfo typeInfo = ConstructedGenericTypeTable.Table.GetOrAdd(key); typeInfo.EstablishDebugName(); return(typeInfo); }
public sealed override bool IsAssignableFrom(Type c) { if (c == null) { return(false); } if (object.ReferenceEquals(c, this)) { return(true); } c = c.UnderlyingSystemType; Type typeInfo = c; RuntimeTypeInfo toTypeInfo = this; if (typeInfo == null || !typeInfo.IsRuntimeImplemented()) { return(false); // Desktop compat: If typeInfo is null, or implemented by a different Reflection implementation, return "false." } RuntimeTypeInfo fromTypeInfo = typeInfo.CastToRuntimeTypeInfo(); if (toTypeInfo.Equals(fromTypeInfo)) { return(true); } RuntimeTypeHandle toTypeHandle = toTypeInfo.InternalTypeHandleIfAvailable; RuntimeTypeHandle fromTypeHandle = fromTypeInfo.InternalTypeHandleIfAvailable; bool haveTypeHandles = !(toTypeHandle.IsNull() || fromTypeHandle.IsNull()); if (haveTypeHandles) { // If both types have type handles, let MRT handle this. It's not dependent on metadata. if (ReflectionCoreExecution.ExecutionEnvironment.IsAssignableFrom(toTypeHandle, fromTypeHandle)) { return(true); } // Runtime IsAssignableFrom does not handle casts from generic type definitions: always returns false. For those, we fall through to the // managed implementation. For everyone else, return "false". // // Runtime IsAssignableFrom does not handle pointer -> UIntPtr cast. if (!(fromTypeInfo.IsGenericTypeDefinition || fromTypeInfo.IsPointer)) { return(false); } } // If we got here, the types are open, or reduced away, or otherwise lacking in type handles. Perform the IsAssignability check in managed code. return(Assignability.IsAssignableFrom(this, typeInfo)); }
/// <summary> /// Return the RuntimeTypeHandle for the named type described in metadata. This is used to implement the Create and Invoke /// apis for types. /// /// Preconditions: /// metadataReader + typeDefHandle - a valid metadata reader + typeDefinitionHandle where "metadataReader" is one /// of the metadata readers returned by ExecutionEnvironment.MetadataReaders. /// /// Note: Although this method has a "bool" return value like the other mapping table accessors, the Project N pay-for-play design /// guarantees that any type enabled for metadata also has a RuntimeTypeHandle underneath. /// </summary> /// <param name="metadataReader">Metadata reader for module containing the type</param> /// <param name="typeDefHandle">TypeDef handle for the type to look up</param> /// <param name="runtimeTypeHandle">Runtime type handle (EEType) for the given type</param> public unsafe bool TryGetNamedTypeForMetadata(QTypeDefinition qTypeDefinition, out RuntimeTypeHandle runtimeTypeHandle) { runtimeTypeHandle = default(RuntimeTypeHandle); NamedTypeLookupResult result = _metadataToRuntimeTypeHandleHashtable.GetOrCreateValue(qTypeDefinition); if (result.VersionNumber <= _namedTypeLookupLiveVersion) { runtimeTypeHandle = result.RuntimeTypeHandle; } return(!runtimeTypeHandle.IsNull()); }
internal static RuntimeTypeHandle FindTypeSupportDynamic(Func <RuntimeTypeHandle, bool> predicate) { for (int i = 0; i < s_moduleCount; i++) { RuntimeTypeHandle info = s_modules[i].FindTypeSupportDynamic(predicate); if (!info.IsNull()) { return(info); } } return(default(RuntimeTypeHandle)); }
/// <summary> /// Given a GUID, retrieve the corresponding type(s) /// </summary> internal static IEnumerable <RuntimeTypeHandle> GetTypesFromGuid(ref Guid guid) { List <RuntimeTypeHandle> rets = new List <RuntimeTypeHandle>(s_moduleCount); for (int i = 0; i < s_moduleCount; ++i) { RuntimeTypeHandle ret = s_modules[i].GetTypeFromGuid(ref guid); if (!ret.IsNull()) { rets.Add(ret); } } return(rets); }
private static void ValidateElementType(RuntimeTypeInfo elementType, RuntimeTypeHandle typeHandle, bool multiDim, int rank) { Debug.Assert(multiDim || rank == 1); if (elementType.IsByRef || elementType.IsByRefLike) { throw new TypeLoadException(SR.Format(SR.ArgumentException_InvalidArrayElementType, elementType)); } // We only permit creating parameterized types if the pay-for-play policy specifically allows them *or* if the result // type would be an open type. if (typeHandle.IsNull() && !elementType.ContainsGenericParameters && !(elementType is RuntimeCLSIDTypeInfo)) { throw ReflectionCoreExecution.ExecutionDomain.CreateMissingArrayTypeException(elementType, multiDim, rank); } }
private static RuntimeTypeHandle GetRuntimeTypeHandleIfAny(RuntimeTypeInfo elementType) { RuntimeTypeHandle elementTypeHandle = elementType.InternalTypeHandleIfAvailable; if (elementTypeHandle.IsNull()) { return(default(RuntimeTypeHandle)); } RuntimeTypeHandle typeHandle; if (!ReflectionCoreExecution.ExecutionEnvironment.TryGetPointerTypeForTargetType(elementTypeHandle, out typeHandle)) { return(default(RuntimeTypeHandle)); } return(typeHandle); }
private static RuntimeArrayTypeInfo WithVerifiedTypeHandle(this RuntimeArrayTypeInfo arrayType, RuntimeTypeInfo elementType) { // We only permit creating parameterized types if the pay-for-play policy specifically allows them *or* if the result // type would be an open type. RuntimeTypeHandle typeHandle = arrayType.InternalTypeHandleIfAvailable; if (IsTypeConstructionEagerlyValidated && typeHandle.IsNull() && !elementType.ContainsGenericParameters #if FEATURE_COMINTEROP && !(elementType is RuntimeCLSIDTypeInfo) #endif ) { throw ReflectionCoreExecution.ExecutionDomain.CreateMissingArrayTypeException(elementType, isMultiDim: false, 1); } return(arrayType); }
/// <summary> /// Return the RuntimeTypeHandle for the named type described in metadata. This is used to implement the Create and Invoke /// apis for types. /// /// Preconditions: /// metadataReader + typeDefHandle - a valid metadata reader + typeDefinitionHandle where "metadataReader" is one /// of the metadata readers returned by ExecutionEnvironment.MetadataReaders. /// /// Note: Although this method has a "bool" return value like the other mapping table accessors, the Project N pay-for-play design /// guarantees that any type enabled for metadata also has a RuntimeTypeHandle underneath. /// </summary> /// <param name="metadataReader">Metadata reader for module containing the type</param> /// <param name="typeDefHandle">TypeDef handle for the type to look up</param> /// <param name="runtimeTypeHandle">Runtime type handle (EEType) for the given type</param> public unsafe bool TryGetNamedTypeForMetadata(MetadataReader metadataReader, TypeDefinitionHandle typeDefHandle, out RuntimeTypeHandle runtimeTypeHandle) { NamedTypeMetadataDescription description = new NamedTypeMetadataDescription() { MetadataReader = metadataReader, TypeDefinition = typeDefHandle }; runtimeTypeHandle = default(RuntimeTypeHandle); NamedTypeLookupResult result = _metadataToRuntimeTypeHandleHashtable.GetOrCreateValue(description); if (result.VersionNumber <= _namedTypeLookupLiveVersion) { runtimeTypeHandle = result.RuntimeTypeHandle; } return(!runtimeTypeHandle.IsNull()); }
internal static NativeFormatRuntimeNamedTypeInfo GetRuntimeNamedTypeInfo(MetadataReader metadataReader, TypeDefinitionHandle typeDefHandle, RuntimeTypeHandle precomputedTypeHandle) { RuntimeTypeHandle typeHandle = precomputedTypeHandle; if (typeHandle.IsNull()) { if (!ReflectionCoreExecution.ExecutionEnvironment.TryGetNamedTypeForMetadata(new QTypeDefinition(metadataReader, typeDefHandle), out typeHandle)) { typeHandle = default(RuntimeTypeHandle); } } UnificationKey key = new UnificationKey(metadataReader, typeDefHandle, typeHandle); NativeFormatRuntimeNamedTypeInfo type = NamedTypeTable.Table.GetOrAdd(key); type.EstablishDebugName(); return(type); }
internal static RuntimeArrayTypeInfo GetArrayTypeInfo(RuntimeTypeInfo elementType, bool multiDim, int rank, RuntimeTypeHandle precomputedTypeHandle) { Debug.Assert(multiDim || rank == 1); RuntimeTypeHandle typeHandle = precomputedTypeHandle.IsNull() ? GetRuntimeTypeHandleIfAny(elementType, multiDim, rank) : precomputedTypeHandle; UnificationKey key = new UnificationKey(elementType, typeHandle); RuntimeArrayTypeInfo type; if (!multiDim) { type = ArrayTypeTable.Table.GetOrAdd(key); } else { type = TypeTableForMultiDimArrayTypeTables.Table.GetOrAdd(rank).GetOrAdd(key); } type.EstablishDebugName(); return(type); }
/// <summary> /// Returns the requested interface pointer specified by itfType from the CCWActivationFactory /// object instance. Typically the requested interface is the /// System.Runtime.InteropServices.WindowsRuntime.IActivationFactory interface. /// </summary> public unsafe int GetCCWActivationFactory(HSTRING activatableClassId, RuntimeTypeHandle itfType, IntPtr *factoryOut) { try { string classId = McgMarshal.HStringToString(activatableClassId); if (classId == null) { return(Interop.COM.E_INVALIDARG); } RuntimeTypeHandle factoryTypeHandle = default(RuntimeTypeHandle); if (m_ccwFactoriesNameMap != null) { int slot = m_ccwFactoriesNameMap.FindString(classId); if (slot >= 0) { factoryTypeHandle = m_ccwFactories[slot].FactoryType; } } if (factoryTypeHandle.IsNull()) { return(Interop.COM.E_NOINTERFACE); } object factory = InteropExtensions.RuntimeNewObject(factoryTypeHandle); *factoryOut = McgMarshal.ObjectToComInterface( factory, itfType); } catch (Exception ex) { *factoryOut = default(IntPtr); return(McgMarshal.GetHRForExceptionWinRT(ex)); } return(Interop.COM.S_OK); }
private static RuntimeTypeHandle GetRuntimeTypeHandleIfAny(RuntimeTypeInfo elementType, bool multiDim, int rank) { Debug.Assert(multiDim || rank == 1); RuntimeTypeHandle elementTypeHandle = elementType.InternalTypeHandleIfAvailable; if (elementTypeHandle.IsNull()) { return(default(RuntimeTypeHandle)); } // The check is here on purpose - one of the implementations of IsByRefLike contains a custom attribute // search and those are very expensive from size on disk footprint perspective. We purposefully // place this call in a path that won't be part of the executable image unless more advanced reflection services // are also needed ("pay for play"). We really don't want a typeof() to push the app into requiring the full reflection // stack to be compiled into the final executable. if (elementType.IsByRefLike) { throw new TypeLoadException(SR.Format(SR.ArgumentException_InvalidArrayElementType, elementType)); } RuntimeTypeHandle typeHandle; if (!multiDim) { if (!ReflectionCoreExecution.ExecutionEnvironment.TryGetArrayTypeForElementType(elementTypeHandle, out typeHandle)) { return(default(RuntimeTypeHandle)); } } else { if (!ReflectionCoreExecution.ExecutionEnvironment.TryGetMultiDimArrayTypeForElementType(elementTypeHandle, rank, out typeHandle)) { return(default(RuntimeTypeHandle)); } } return(typeHandle); }
private static RuntimeTypeHandle GetRuntimeTypeHandleIfAny(RuntimeTypeInfo genericTypeDefinition, RuntimeTypeInfo[] genericTypeArguments) { RuntimeTypeHandle genericTypeDefinitionHandle = genericTypeDefinition.InternalTypeHandleIfAvailable; if (genericTypeDefinitionHandle.IsNull()) { return(default(RuntimeTypeHandle)); } if (ReflectionCoreExecution.ExecutionEnvironment.IsReflectionBlocked(genericTypeDefinitionHandle)) { return(default(RuntimeTypeHandle)); } int count = genericTypeArguments.Length; RuntimeTypeHandle[] genericTypeArgumentHandles = new RuntimeTypeHandle[count]; for (int i = 0; i < count; i++) { RuntimeTypeHandle genericTypeArgumentHandle = genericTypeArguments[i].InternalTypeHandleIfAvailable; if (genericTypeArgumentHandle.IsNull()) { return(default(RuntimeTypeHandle)); } genericTypeArgumentHandles[i] = genericTypeArgumentHandle; } RuntimeTypeHandle typeHandle; if (!ReflectionCoreExecution.ExecutionEnvironment.TryGetConstructedGenericTypeForComponents(genericTypeDefinitionHandle, genericTypeArgumentHandles, out typeHandle)) { return(default(RuntimeTypeHandle)); } return(typeHandle); }
private static RuntimeConstructedGenericTypeInfo WithVerifiedTypeHandle(this RuntimeConstructedGenericTypeInfo genericType, RuntimeTypeInfo[] genericTypeArguments) { // We only permit creating parameterized types if the pay-for-play policy specifically allows them *or* if the result // type would be an open type. RuntimeTypeHandle typeHandle = genericType.InternalTypeHandleIfAvailable; if (IsTypeConstructionEagerlyValidated && typeHandle.IsNull()) { bool atLeastOneOpenType = false; foreach (RuntimeTypeInfo genericTypeArgument in genericTypeArguments) { if (genericTypeArgument.ContainsGenericParameters) { atLeastOneOpenType = true; } } if (!atLeastOneOpenType) { throw ReflectionCoreExecution.ExecutionDomain.CreateMissingConstructedGenericTypeException(genericType.GetGenericTypeDefinition(), genericTypeArguments.CloneTypeArray()); } } return(genericType); }
// Todo: This is looking up the hierarchy to DefType and ParameterizedType. It should really // call a virtual or an outside type to handle those parts internal bool RetrieveRuntimeTypeHandleIfPossible() { TypeDesc type = this; if (!type.RuntimeTypeHandle.IsNull()) { return(true); } TypeBuilderState state = GetTypeBuilderStateIfExist(); if (state != null && state.AttemptedAndFailedToRetrieveTypeHandle) { return(false); } if (type is DefType) { DefType typeAsDefType = (DefType)type; TypeDesc typeDefinition = typeAsDefType.GetTypeDefinition(); RuntimeTypeHandle typeDefHandle = typeDefinition.RuntimeTypeHandle; if (typeDefHandle.IsNull()) { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING NativeFormat.NativeFormatType mdType = typeDefinition as NativeFormat.NativeFormatType; if (mdType != null) { // Look up the runtime type handle in the module metadata if (TypeLoaderEnvironment.Instance.TryGetNamedTypeForMetadata(new QTypeDefinition(mdType.MetadataReader, mdType.Handle), out typeDefHandle)) { typeDefinition.SetRuntimeTypeHandleUnsafe(typeDefHandle); } } #endif #if ECMA_METADATA_SUPPORT Ecma.EcmaType ecmaType = typeDefinition as Ecma.EcmaType; if (ecmaType != null) { // Look up the runtime type handle in the module metadata if (TypeLoaderEnvironment.Instance.TryGetNamedTypeForMetadata(new QTypeDefinition(ecmaType.MetadataReader, ecmaType.Handle), out typeDefHandle)) { typeDefinition.SetRuntimeTypeHandleUnsafe(typeDefHandle); } } #endif } if (!typeDefHandle.IsNull()) { Instantiation instantiation = typeAsDefType.Instantiation; if ((instantiation.Length > 0) && !typeAsDefType.IsGenericDefinition) { // Generic type. First make sure we have type handles for the arguments, then check // the instantiation. bool argumentsRegistered = true; bool arrayArgumentsFound = false; for (int i = 0; i < instantiation.Length; i++) { if (!instantiation[i].RetrieveRuntimeTypeHandleIfPossible()) { argumentsRegistered = false; arrayArgumentsFound = arrayArgumentsFound || (instantiation[i] is ArrayType); } } RuntimeTypeHandle rtth; // If at least one of the arguments is not known to the runtime, we take a slower // path to compare the current type we need a handle for to the list of generic // types statically available, by loading them as DefTypes and doing a DefType comparaison if ((argumentsRegistered && TypeLoaderEnvironment.Instance.TryLookupConstructedGenericTypeForComponents(new TypeLoaderEnvironment.HandleBasedGenericTypeLookup(typeAsDefType), out rtth)) || (arrayArgumentsFound && TypeLoaderEnvironment.Instance.TryLookupConstructedGenericTypeForComponents(new TypeLoaderEnvironment.DefTypeBasedGenericTypeLookup(typeAsDefType), out rtth))) { typeAsDefType.SetRuntimeTypeHandleUnsafe(rtth); return(true); } } else { // Nongeneric, or generic type def types are just the type handle of the type definition as found above type.SetRuntimeTypeHandleUnsafe(typeDefHandle); return(true); } } } else if (type is ParameterizedType) { ParameterizedType typeAsParameterType = (ParameterizedType)type; if (typeAsParameterType.ParameterType.RetrieveRuntimeTypeHandleIfPossible()) { RuntimeTypeHandle rtth; if ((type is ArrayType && (TypeLoaderEnvironment.Instance.TryGetArrayTypeForElementType_LookupOnly(typeAsParameterType.ParameterType.RuntimeTypeHandle, type.IsMdArray, type.IsMdArray ? ((ArrayType)type).Rank : -1, out rtth) || TypeLoaderEnvironment.Instance.TryGetArrayTypeHandleForNonDynamicArrayTypeFromTemplateTable(type as ArrayType, out rtth))) || (type is PointerType && TypeSystemContext.PointerTypesCache.TryGetValue(typeAsParameterType.ParameterType.RuntimeTypeHandle, out rtth))) { typeAsParameterType.SetRuntimeTypeHandleUnsafe(rtth); return(true); } else if (type is ByRefType) { // Byref types don't have any associated type handles, so return success at this point // since we were able to resolve the typehandle of the element type return(true); } } } else if (type is SignatureVariable) { // SignatureVariables do not have RuntimeTypeHandles } else { Debug.Assert(false); } // Make a note on the type build state that we have attempted to retrieve RuntimeTypeHandle but there is not one GetOrCreateTypeBuilderState().AttemptedAndFailedToRetrieveTypeHandle = true; return(false); }
private bool FindMatchingInterfaceSlot(NativeFormatModuleInfo module, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle instanceTypeHandle, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch, bool defaultMethods) { uint numTargetImplementations = entryParser.GetUnsigned(); #if GVM_RESOLUTION_TRACE Debug.WriteLine(" :: Declaring type = " + GetTypeNameDebug(declaringType)); Debug.WriteLine(" :: Target type = " + GetTypeNameDebug(openTargetTypeHandle)); #endif for (uint j = 0; j < numTargetImplementations; j++) { uint nameAndSigToken = entryParser.GetUnsigned(); MethodNameAndSignature targetMethodNameAndSignature = null; RuntimeTypeHandle targetTypeHandle = default; bool isDefaultInterfaceMethodImplementation; if (nameAndSigToken != SpecialGVMInterfaceEntry.Diamond && nameAndSigToken != SpecialGVMInterfaceEntry.Reabstraction) { targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, nameAndSigToken); targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); isDefaultInterfaceMethodImplementation = RuntimeAugments.IsInterface(targetTypeHandle); #if GVM_RESOLUTION_TRACE Debug.WriteLine(" Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle)); #endif } else { isDefaultInterfaceMethodImplementation = true; } uint numIfaceImpls = entryParser.GetUnsigned(); for (uint k = 0; k < numIfaceImpls; k++) { RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); #if GVM_RESOLUTION_TRACE Debug.WriteLine(" -> Current implementing type = " + GetTypeNameDebug(implementingTypeHandle)); #endif uint numIfaceSigs = entryParser.GetUnsigned(); if (!openTargetTypeHandle.Equals(implementingTypeHandle) || defaultMethods != isDefaultInterfaceMethodImplementation) { // 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, entryParser.GetUnsigned()); if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(ref ifaceSigParser, module.Handle, targetTypeInstantiation, null, out currentIfaceTypeHandle)) { #if GVM_RESOLUTION_TRACE Debug.WriteLine(" -> Current interface on type = " + GetTypeNameDebug(currentIfaceTypeHandle)); #endif Debug.Assert(!currentIfaceTypeHandle.IsNull()); if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) || (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle))) { #if GVM_RESOLUTION_TRACE Debug.WriteLine(" " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!"); #endif if (targetMethodNameAndSignature == null) { if (nameAndSigToken == SpecialGVMInterfaceEntry.Diamond) { throw new AmbiguousImplementationException(); } else { Debug.Assert(nameAndSigToken == SpecialGVMInterfaceEntry.Reabstraction); throw new EntryPointNotFoundException(); } } // 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 if (!RuntimeAugments.IsInterface(targetTypeHandle) || !RuntimeAugments.IsGenericTypeDefinition(targetTypeHandle)) { // Not a default interface method or default interface method on a non-generic type. // We have a usable type handle. declaringType = targetTypeHandle; } else if (RuntimeAugments.IsGenericType(currentIfaceTypeHandle) && RuntimeAugments.GetGenericDefinition(currentIfaceTypeHandle).Equals(targetTypeHandle)) { // Default interface method implemented on the same type that declared the slot. // Use the instantiation as-is from what we found. declaringType = currentIfaceTypeHandle; } else { declaringType = default; // Default interface method implemented on a different generic interface. // We need to find a usable instantiation. There should be only one match because we // would be dealing with a diamond otherwise. int numInstanceInterfaces = RuntimeAugments.GetInterfaceCount(instanceTypeHandle); for (int instIntfIndex = 0; instIntfIndex < numInstanceInterfaces; instIntfIndex++) { RuntimeTypeHandle instIntf = RuntimeAugments.GetInterface(instanceTypeHandle, instIntfIndex); if (RuntimeAugments.IsGenericType(instIntf) && RuntimeAugments.GetGenericDefinition(instIntf).Equals(targetTypeHandle)) { // Got a potential interface. Check if the implementing interface is in the interface // list. We don't want IsAssignableFrom because we need an exact match. int numIntInterfaces = RuntimeAugments.GetInterfaceCount(instIntf); for (int intIntfIndex = 0; intIntfIndex < numIntInterfaces; intIntfIndex++) { if (RuntimeAugments.GetInterface(instIntf, intIntfIndex).Equals(currentIfaceTypeHandle)) { Debug.Assert(declaringType.IsNull()); declaringType = instIntf; #if !DEBUG break; #endif } } #if !DEBUG if (!declaringType.IsNull()) { break; } #endif } } Debug.Assert(!declaringType.IsNull()); } methodNameAndSignature = targetMethodNameAndSignature; return(true); } } } } } return(false); }
/// <summary> /// Returns the existing RCW or create a new RCW from the COM interface pointer /// NOTE: This does not do any unboxing at all. /// </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> private static object ComInterfaceToComObjectInternal_NoCache( IntPtr pComItf, IntPtr pComIdentityIUnknown, RuntimeTypeHandle interfaceType, RuntimeTypeHandle classTypeInSignature, ContextCookie expectedContext, CreateComObjectFlags flags, out string className ) { className = null; // // Lookup RCW in global RCW cache based on the identity IUnknown // __ComObject comObject = ComObjectCache.Lookup(pComIdentityIUnknown); if (comObject != null) { bool useThisComObject = true; if (!expectedContext.IsDefault) { // // Make sure the returned RCW matches the context we specify (if any) // if (!comObject.IsFreeThreaded && !comObject.ContextCookie.Equals(expectedContext)) { // // This is a mismatch. // We only care about context for WinRT factory RCWs (which is the only place we are // passing in the context right now). // When we get back a WinRT factory RCW created in a different context. This means the // factory is a singleton, and the returned IActivationFactory could be either one of // the following: // 1) A raw pointer, and it acts like a free threaded object // 2) A proxy that is used across different contexts. It might maintain a list of contexts // that it is marshaled to, and will fail to be called if it is not marshaled to this // context yet. // // In this case, it is unsafe to use this RCW in this context and we should proceed // to create a duplicated one instead. It might make sense to have a context-sensitive // RCW cache but I don't think this case will be common enough to justify it // // @TODO: Check for DCOM proxy as well useThisComObject = false; } } if (useThisComObject) { // // We found one - AddRef and return // comObject.AddRef(); return(comObject); } } string winrtClassName = null; bool isSealed = false; if (!classTypeInSignature.IsNull()) { isSealed = classTypeInSignature.IsSealed(); } // // Only look at runtime class name if the class type in signature is not sealed // NOTE: In the case of System.Uri, we are not pass the class type, only the interface // if (!isSealed && (flags & CreateComObjectFlags.SkipTypeResolutionAndUnboxing) == 0) { IntPtr pInspectable; bool needRelease = false; if (interfaceType.IsSupportIInspectable()) { // // Use the interface pointer as IInspectable as we know it is indeed a WinRT interface that // derives from IInspectable // pInspectable = pComItf; } else if ((flags & CreateComObjectFlags.IsWinRTObject) != 0) { // // Otherwise, if someone tells us that this is a WinRT object, but we don't have a // IInspectable interface at hand, we'll QI for it // pInspectable = McgMarshal.ComQueryInterfaceNoThrow(pComItf, ref Interop.COM.IID_IInspectable); needRelease = true; } else { pInspectable = default(IntPtr); } try { if (pInspectable != default(IntPtr)) { className = McgComHelpers.GetRuntimeClassName(pInspectable); winrtClassName = className; } } finally { if (needRelease && pInspectable != default(IntPtr)) { McgMarshal.ComRelease(pInspectable); pInspectable = default(IntPtr); } } } // // 1. Prefer using the class returned from GetRuntimeClassName // 2. Otherwise use the class (if there) in the signature // 3. Out of options - create __ComObject // RuntimeTypeHandle classTypeToCreateRCW = default(RuntimeTypeHandle); RuntimeTypeHandle interfaceTypeFromName = default(RuntimeTypeHandle); if (!String.IsNullOrEmpty(className)) { if (!McgModuleManager.TryGetClassTypeFromName(className, out classTypeToCreateRCW)) { // // If we can't find the class name in our map, try interface as well // Such as IVector<Int32> // This apparently won't work if we haven't seen the interface type in MCG // McgModuleManager.TryGetInterfaceTypeFromName(className, out interfaceTypeFromName); } } if (classTypeToCreateRCW.IsNull()) { classTypeToCreateRCW = classTypeInSignature; } // Use identity IUnknown to create the new RCW // @TODO: Transfer the ownership of ref count to the RCW if (classTypeToCreateRCW.IsNull()) { // // Create a weakly typed RCW because we have no information about this particular RCW // @TODO - what if this RCW is not seen by MCG but actually exists in WinMD and therefore we // are missing GCPressure and ComMarshallingType information for this object? // comObject = new __ComObject(pComIdentityIUnknown, default(RuntimeTypeHandle)); } else { // // Create a strongly typed RCW based on RuntimeTypeHandle // comObject = CreateComObjectInternal(classTypeToCreateRCW, pComIdentityIUnknown); // Use identity IUnknown to create the new RCW } #if DEBUG // // Remember the runtime class name for debugging purpose // This way you can tell what the class name is, even when we failed to create a strongly typed // RCW for it // comObject.m_runtimeClassName = className; #endif // // Make sure we QI for that interface // if (!interfaceType.IsNull()) { comObject.QueryInterface_NoAddRef_Internal(interfaceType, /* cacheOnly= */ false, /* throwOnQueryInterfaceFailure= */ false); } return(comObject); }
/// <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); }
private bool FindMatchingInterfaceSlot(NativeFormatModuleInfo module, 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.GetExternalNativeLayoutOffset(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, 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.GetExternalNativeLayoutOffset(entryParser.GetUnsigned())); if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(ref ifaceSigParser, module.Handle, targetTypeInstantiation, null, out currentIfaceTypeHandle)) { 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); }