private static TypeInfo resolveGenericTypeDefinition(TypeInfo parent) { var shouldUseGenericType = !(parent.IsGenericType && parent.GetGenericTypeDefinition().GetTypeInfo() != parent); if (parent.IsGenericType && shouldUseGenericType) parent = parent.GetGenericTypeDefinition().GetTypeInfo(); return parent; }
private static bool TryGetMapping(TypeInfo firstGenericType, Type sourceType, Type targetType, string targetName, string prefix, ref TargetMapping mapping) { if (firstGenericType.GetGenericTypeDefinition() == sourceType.GetTypeInfo()) { // Not crazy about this, but a lot of mapping work happens in the constructors here mapping = ReflectionHelpers.CreateInstanceOfType<TargetMapping>(targetType.GetTypeInfo(), firstGenericType, targetName, prefix, firstGenericType); return true; } return false; }
//----------------------------------------------------------------------------------------------------------------------------------------------------- private static bool IsNullableValueType(System.Reflection.TypeInfo typeInfo, out Type underlyingValueType) { if (typeInfo.IsGenericType && !typeInfo.IsGenericTypeDefinition && typeInfo.GetGenericTypeDefinition() == typeof(Nullable <>)) { underlyingValueType = typeInfo.GetGenericArguments()[0]; return(true); } underlyingValueType = null; return(false); }
public static bool IsAssignableFrom(TypeInfo toTypeInfo, TypeInfo fromTypeInfo, FoundationTypes foundationTypes) { if (toTypeInfo == null) throw new NullReferenceException(); if (fromTypeInfo == null) return false; // It would be more appropriate to throw ArgumentNullException here, but returning "false" is the desktop-compat behavior. if (fromTypeInfo.Equals(toTypeInfo)) return true; if (toTypeInfo.IsGenericTypeDefinition) { // Asking whether something can cast to a generic type definition is arguably meaningless. The desktop CLR Reflection layer converts all // generic type definitions to generic type instantiations closed over the formal generic type parameters. The .NET Native framework // keeps the two separate. Fortunately, under either interpretation, returning "false" unless the two types are identical is still a // defensible behavior. To avoid having the rest of the code deal with the differing interpretations, we'll short-circuit this now. return false; } if (fromTypeInfo.IsGenericTypeDefinition) { // The desktop CLR Reflection layer converts all generic type definitions to generic type instantiations closed over the formal // generic type parameters. The .NET Native framework keeps the two separate. For the purpose of IsAssignableFrom(), // it makes sense to unify the two for the sake of backward compat. We'll just make the transform here so that the rest of code // doesn't need to know about this quirk. fromTypeInfo = fromTypeInfo.GetGenericTypeDefinition().MakeGenericType(fromTypeInfo.GenericTypeParameters).GetTypeInfo(); } if (fromTypeInfo.CanCastTo(toTypeInfo, foundationTypes)) return true; Type toType = toTypeInfo.AsType(); Type fromType = fromTypeInfo.AsType(); // Desktop compat: IsAssignableFrom() considers T as assignable to Nullable<T> (but does not check if T is a generic parameter.) if (!fromType.IsGenericParameter) { Type nullableUnderlyingType = Nullable.GetUnderlyingType(toType); if (nullableUnderlyingType != null && nullableUnderlyingType.Equals(fromType)) return true; } return false; }
// // T[] casts to IList<T>. This could be handled by the normal ancestor-walking code // but for one complication: T[] also casts to IList<U> if T[] casts to U[]. // private static bool CanCastArrayToInterface(this TypeInfo fromTypeInfo, TypeInfo toTypeInfo, FoundationTypes foundationTypes) { Debug.Assert(fromTypeInfo.IsArray); Debug.Assert(toTypeInfo.IsInterface); Type toType = toTypeInfo.AsType(); if (toType.IsConstructedGenericType) { Type[] toTypeGenericTypeArguments = toTypeInfo.GenericTypeArguments; if (toTypeGenericTypeArguments.Length != 1) return false; TypeInfo toElementTypeInfo = toTypeGenericTypeArguments[0].GetTypeInfo(); Type toTypeGenericTypeDefinition = toTypeInfo.GetGenericTypeDefinition(); TypeInfo fromElementTypeInfo = fromTypeInfo.GetElementType().GetTypeInfo(); foreach (Type ifc in fromTypeInfo.ImplementedInterfaces) { if (ifc.IsConstructedGenericType) { Type ifcGenericTypeDefinition = ifc.GetGenericTypeDefinition(); if (ifcGenericTypeDefinition.Equals(toTypeGenericTypeDefinition)) { if (fromElementTypeInfo.IsElementTypeCompatibleWith(toElementTypeInfo, foundationTypes)) return true; } } } return false; } else { foreach (Type ifc in fromTypeInfo.ImplementedInterfaces) { if (ifc.Equals(toType)) return true; } return false; } }
private static ResolvedPropertyTypeInfo Parse(TypeInfo propertyTypeInfo, Boolean throwException) { if (propertyTypeInfo == null) { throw Logger.Fatal.ArgumentNull(nameof(propertyTypeInfo)); } if (!propertyTypeInfo.IsGenericType) { if (!throwException) { return null; } throw Logger.Fatal.ArgumentFormat( nameof(propertyTypeInfo), SR.ResolveResultFactory_PropertyTypeNotGeneric, propertyTypeInfo ); } var interfaceType = propertyTypeInfo.GetGenericTypeDefinition(); if (!KnownPropertyTypeDefinitions.Contains(interfaceType)) { if (!throwException) { return null; } throw InvalidInterfaceType(nameof(propertyTypeInfo), interfaceType); } return new ResolvedPropertyTypeInfo() { InterfaceType = interfaceType, ResolvedType = propertyTypeInfo.GenericTypeArguments.First(), }; }
private static bool IsGenericIEnumerable (TypeInfo enumerableType) { return IsIEnumerable (enumerableType) && enumerableType.IsGenericType && enumerableType.GetGenericTypeDefinition() == typeof (IEnumerable<>); }
private bool IsSupportedImportManyType(TypeInfo typeInfo) { return typeInfo.IsArray || (typeInfo.IsGenericTypeDefinition && s_supportedImportManyTypes.Contains(typeInfo.AsType())) || (typeInfo.AsType().IsConstructedGenericType && s_supportedImportManyTypes.Contains(typeInfo.GetGenericTypeDefinition())); }
/// <summary> /// Determines whether the provided interface is a closed generic of the specified open generic contract. /// </summary> /// <param name="openGenericContract">The open generic contract.</param> /// <param name="exportInterface">The export interface.</param> /// <returns><c>true</c> if the provided interface is a closed generic of the specified open generic contract, otherwise <c>false</c>.</returns> private bool IsClosedGenericOf(TypeInfo openGenericContract, TypeInfo exportInterface) { return exportInterface.IsGenericType && exportInterface.GetGenericTypeDefinition() == openGenericContract.AsType(); }
private CommonObjectFormatter.Builder FormatObjectRecursive( CommonObjectFormatter.Builder result, object obj, bool isRoot) { string str = this._formatter.PrimitiveFormatter.FormatPrimitive(obj, this._primitiveOptions); if (str != null) { result.Append(str, 0, int.MaxValue); return(result); } Type type = obj.GetType(); System.Reflection.TypeInfo typeInfo = IntrospectionExtensions.GetTypeInfo(type); if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == (object)typeof(KeyValuePair <,>)) { if (isRoot) { result.Append(this._formatter.TypeNameFormatter.FormatTypeName(type), 0, int.MaxValue); result.Append(' '); } this.FormatKeyValuePair(result, obj); return(result); } if (typeInfo.IsArray) { if (this.VisitedObjects.Add(obj)) { this.FormatArray(result, (Array)obj); this.VisitedObjects.Remove(obj); } else { result.AppendInfiniteRecursionMarker(); } return(result); } bool flag = false; ICollection collection = null; if (obj is ICollection) { collection = (ICollection)obj; this.FormatCollectionHeader(result, collection); } else if (ObjectFormatterHelpers.HasOverriddenToString(typeInfo)) { this.ObjectToString(result, obj); flag = true; } else { result.Append(this._formatter.TypeNameFormatter.FormatTypeName(type), 0, int.MaxValue); } if (!flag) { this.FormatMembers(result, obj); } return(result); }
// Method to compare two types pointers for type equality // We cannot just compare the pointers as there can be duplicate type instances // for cloned and constructed types. static bool AreTypesEquivalentInternal(TypeInfo pType1, TypeInfo pType2) { if (!pType1.IsInstantiatedTypeInfo() && !pType2.IsInstantiatedTypeInfo()) return pType1.Equals(pType2); if (pType1.IsGenericType && pType2.IsGenericType) { if (!pType1.GetGenericTypeDefinition().Equals(pType2.GetGenericTypeDefinition())) return false; Type[] args1 = pType1.GenericTypeArguments; Type[] args2 = pType2.GenericTypeArguments; Debug.Assert(args1.Length == args2.Length); for (int i = 0; i < args1.Length; i++) { if (!AreTypesEquivalentInternal(args1[i].GetTypeInfo(), args2[i].GetTypeInfo())) return false; } return true; } if (pType1.IsArray && pType2.IsArray) { if (pType1.GetArrayRank() != pType2.GetArrayRank()) return false; return AreTypesEquivalentInternal(pType1.GetElementType().GetTypeInfo(), pType2.GetElementType().GetTypeInfo()); } if (pType1.IsPointer && pType2.IsPointer) { return AreTypesEquivalentInternal(pType1.GetElementType().GetTypeInfo(), pType2.GetElementType().GetTypeInfo()); } return false; }
static bool ImplementsInterface(TypeInfo pObjType, TypeInfo pTargetType) { Debug.Assert(!pTargetType.IsArray, "did not expect array type"); Debug.Assert(pTargetType.IsInterface, "IsInstanceOfInterface called with non-interface EEType"); foreach (var pInterfaceType in pObjType.ImplementedInterfaces) { if (AreTypesEquivalentInternal(pInterfaceType.GetTypeInfo(), pTargetType)) { return true; } } // We did not find the interface type in the list of supported interfaces. There's still one // chance left: if the target interface is generic and one or more of its type parameters is co or // contra variant then the object can still match if it implements a different instantiation of // the interface with type compatible generic arguments. // // An additional edge case occurs because of array covariance. This forces us to treat any generic // interfaces implemented by arrays as covariant over their one type parameter. // if (pTargetType.HasGenericVariance || (fArrayCovariance && pTargetType.IsGenericType)) // if (pTargetType.IsGenericType) { bool fArrayCovariance = pObjType.IsArray; Type pTargetGenericType = pTargetType.GetGenericTypeDefinition(); // Fetch the instantiations lazily only once we get a potential match Type[] pTargetInstantiation = null; Type[] pTargetGenericInstantiation = null; foreach (var pInterface in pObjType.ImplementedInterfaces) { TypeInfo pInterfaceType = pInterface.GetTypeInfo(); // We can ignore interfaces which are not also marked as having generic variance // unless we're dealing with array covariance. // if (pInterfaceType.HasGenericVariance || (fArrayCovariance && pInterfaceType.IsGenericType)) if (!pInterfaceType.IsGenericType) continue; // If the generic types aren't the same then the types aren't compatible. if (!pInterfaceType.GetGenericTypeDefinition().Equals(pTargetGenericType)) continue; Type[] pInterfaceInstantiation = pInterfaceType.GenericTypeArguments; if (pTargetInstantiation == null) { pTargetInstantiation = pTargetType.GenericTypeArguments; if (!fArrayCovariance) pTargetGenericInstantiation = pTargetGenericType.GetTypeInfo().GenericTypeParameters; } // Compare the instantiations to see if they're compatible taking variance into account. if (TypeParametersAreCompatible(pInterfaceInstantiation, pTargetInstantiation, pTargetGenericInstantiation, fArrayCovariance)) return true; if (fArrayCovariance) { Debug.Assert(pInterfaceInstantiation.Length == 1, "arity mismatch for array generic interface"); Debug.Assert(pTargetInstantiation.Length == 1, "arity mismatch for array generic interface"); // Special case for generic interfaces on arrays. Arrays of integral types (including enums) // can be cast to generic interfaces over the integral types of the same size. For example // int[] . IList<uint>. if (ArePrimitveTypesEquivalentSize(pInterfaceInstantiation[0].GetTypeInfo(), pTargetInstantiation[0].GetTypeInfo())) { // We have checked that the interface type definition matches above. The checks are ordered differently // here compared with rtm\system\runtime\typecast.cs version because of TypeInfo does not let us do // the HasGenericVariance optimization. return true; } } } } return false; }
// Compare two types to see if they are compatible via generic variance. static bool TypesAreCompatibleViaGenericVariance(TypeInfo pSourceType, TypeInfo pTargetType) { Type pTargetGenericType = pTargetType.GetGenericTypeDefinition(); Type pSourceGenericType = pSourceType.GetGenericTypeDefinition(); // If the generic types aren't the same then the types aren't compatible. if (pTargetGenericType.Equals(pSourceGenericType)) { // Compare the instantiations to see if they're compatible taking variance into account. if (TypeParametersAreCompatible(pSourceType.GenericTypeArguments, pTargetType.GenericTypeArguments, pTargetGenericType.GetTypeInfo().GenericTypeParameters, false)) { return true; } } return false; }
private TypeInfo UnwrapNullable(TypeInfo info) { if (info.IsGenericType && info.GetGenericTypeDefinition() == typeof(Nullable<>)) { return info.GenericTypeArguments[0].GetTypeInfo(); } return info; }
public static bool IsNullable(this System.Reflection.TypeInfo type) { return(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable <>)); }
/// <summary> /// Gets the generic type definition. /// </summary> /// <param name="typeInfo">The <see cref="TypeInfo"/>.</param> /// <returns> /// The generic type definition. /// </returns> private ITypeInfo GetGenericTypeDefinition(TypeInfo typeInfo) { if (typeInfo.IsGenericType && !typeInfo.IsGenericTypeDefinition) { return GetRuntimeType(typeInfo.GetGenericTypeDefinition()); } return null; }
// // Check a base type or implemented interface type for equivalence (taking into account variance for generic instantiations.) // Does not check ancestors recursively. // private static bool MatchesWithVariance(this TypeInfo fromTypeInfo, TypeInfo toTypeInfo, FoundationTypes foundationTypes) { Debug.Assert(!(fromTypeInfo.IsArray || fromTypeInfo.IsByRef || fromTypeInfo.IsPointer || fromTypeInfo.IsGenericParameter)); Debug.Assert(!(toTypeInfo.IsArray || toTypeInfo.IsByRef || toTypeInfo.IsPointer || toTypeInfo.IsGenericParameter)); if (fromTypeInfo.Equals(toTypeInfo)) return true; if (!(fromTypeInfo.AsType().IsConstructedGenericType && toTypeInfo.AsType().IsConstructedGenericType)) return false; TypeInfo genericTypeDefinition = fromTypeInfo.GetGenericTypeDefinition().GetTypeInfo(); if (!genericTypeDefinition.AsType().Equals(toTypeInfo.GetGenericTypeDefinition())) return false; Type[] fromTypeArguments = fromTypeInfo.GenericTypeArguments; Type[] toTypeArguments = toTypeInfo.GenericTypeArguments; Type[] genericTypeParameters = genericTypeDefinition.GenericTypeParameters; for (int i = 0; i < genericTypeParameters.Length; i++) { TypeInfo fromTypeArgumentInfo = fromTypeArguments[i].GetTypeInfo(); TypeInfo toTypeArgumentInfo = toTypeArguments[i].GetTypeInfo(); GenericParameterAttributes attributes = genericTypeParameters[i].GetTypeInfo().GenericParameterAttributes; switch (attributes & GenericParameterAttributes.VarianceMask) { case GenericParameterAttributes.Covariant: if (!(fromTypeArgumentInfo.IsGcReferenceTypeAndCastableTo(toTypeArgumentInfo, foundationTypes))) return false; break; case GenericParameterAttributes.Contravariant: if (!(toTypeArgumentInfo.IsGcReferenceTypeAndCastableTo(fromTypeArgumentInfo, foundationTypes))) return false; break; case GenericParameterAttributes.None: if (!(fromTypeArgumentInfo.Equals(toTypeArgumentInfo))) return false; break; default: throw new BadImageFormatException(); // Unexpected variance value in metadata. } } return true; }
public static bool IsNullable(this TypeInfo me) { return(me.IsClass || me.IsGenericType && me.GetGenericTypeDefinition() == typeof(Nullable <>)); }
/// <summary> /// Resolves <see cref="System.Type"/> to a <see cref="TypeSymbol"/> available in this assembly /// its referenced assemblies. /// </summary> /// <param name="type">The type to resolve.</param> /// <param name="includeReferences">Use referenced assemblies for resolution.</param> /// <returns>The resolved symbol if successful or null on failure.</returns> internal TypeSymbol GetTypeByReflectionType(Type type, bool includeReferences) { System.Reflection.TypeInfo typeInfo = type.GetTypeInfo(); Debug.Assert(!typeInfo.IsByRef); // not supported rigth now (we don't accept open types as submission results nor host types): Debug.Assert(!typeInfo.ContainsGenericParameters); if (typeInfo.IsArray) { TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences); if ((object)symbol == null) { return(null); } int rank = typeInfo.GetArrayRank(); return(new ArrayTypeSymbol(this, symbol, ImmutableArray <CustomModifier> .Empty, rank)); } else if (typeInfo.IsPointer) { TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences); if ((object)symbol == null) { return(null); } return(new PointerTypeSymbol(symbol)); } else if (typeInfo.DeclaringType != null) { Debug.Assert(!typeInfo.IsArray); // consolidated generic arguments (includes arguments of all declaring types): Type[] genericArguments = typeInfo.GenericTypeArguments; int typeArgumentIndex = 0; var currentTypeInfo = typeInfo.IsGenericType ? typeInfo.GetGenericTypeDefinition().GetTypeInfo() : typeInfo; var nestedTypes = ArrayBuilder <System.Reflection.TypeInfo> .GetInstance(); while (true) { Debug.Assert(currentTypeInfo.IsGenericTypeDefinition || !currentTypeInfo.IsGenericType); nestedTypes.Add(currentTypeInfo); if (currentTypeInfo.DeclaringType == null) { break; } currentTypeInfo = currentTypeInfo.DeclaringType.GetTypeInfo(); } int i = nestedTypes.Count - 1; var symbol = (NamedTypeSymbol)GetTypeByReflectionType(nestedTypes[i].AsType(), includeReferences); if ((object)symbol == null) { return(null); } while (--i >= 0) { int forcedArity = nestedTypes[i].GenericTypeParameters.Length - nestedTypes[i + 1].GenericTypeParameters.Length; MetadataTypeName mdName = MetadataTypeName.FromTypeName(nestedTypes[i].Name, forcedArity: forcedArity); symbol = symbol.LookupMetadataType(ref mdName); if ((object)symbol == null || symbol.IsErrorType()) { return(null); } symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences); if ((object)symbol == null) { return(null); } } nestedTypes.Free(); Debug.Assert(typeArgumentIndex == genericArguments.Length); return(symbol); } else { AssemblyIdentity assemblyId = AssemblyIdentity.FromAssemblyDefinition(typeInfo.Assembly); MetadataTypeName mdName = MetadataTypeName.FromNamespaceAndTypeName( typeInfo.Namespace ?? string.Empty, typeInfo.Name, forcedArity: typeInfo.GenericTypeArguments.Length); NamedTypeSymbol symbol = GetTopLevelTypeByMetadataName(ref mdName, assemblyId, includeReferences, isWellKnownType: false); if ((object)symbol == null || symbol.IsErrorType()) { return(null); } int typeArgumentIndex = 0; Type[] genericArguments = typeInfo.GenericTypeArguments; symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences); Debug.Assert(typeArgumentIndex == genericArguments.Length); return(symbol); } }
// an (awful) test for a null read-only-array. Is there no better way to do this? private static bool IsDefaultImmutableArray(Object o) { System.Reflection.TypeInfo ti = o.GetType().GetTypeInfo(); return(ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(ImmutableArray <>) && (bool)ti.GetDeclaredMethod("get_IsDefault").Invoke(o, Array.Empty <object>())); }