internal ObjectItemLoadingSessionData(KnownAssembliesSet knownAssemblies, LockedAssemblyCache lockedAssemblyCache, EdmItemCollection edmItemCollection, Action <String> logLoadMessage, object loaderCookie) { Debug.Assert(loaderCookie == null || loaderCookie is Func <Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader>, "This is a bad loader cookie"); _typesInLoading = new Dictionary <string, EdmType>(StringComparer.Ordinal); _errors = new List <EdmItemError>(); _knownAssemblies = knownAssemblies; _lockedAssemblyCache = lockedAssemblyCache; _loadersThatNeedLevel1PostSessionProcessing = new HashSet <ObjectItemAssemblyLoader>(); _loadersThatNeedLevel2PostSessionProcessing = new HashSet <ObjectItemAssemblyLoader>(); _edmItemCollection = edmItemCollection; _loadMessageLogger = new LoadMessageLogger(logLoadMessage); _cspaceToOspace = new Dictionary <EdmType, EdmType>(); _loaderFactory = (Func <Assembly, ObjectItemLoadingSessionData, ObjectItemAssemblyLoader>)loaderCookie; _originalLoaderCookie = loaderCookie; if (_loaderFactory == ObjectItemConventionAssemblyLoader.Create && _edmItemCollection != null) { foreach (KnownAssemblyEntry entry in _knownAssemblies.GetEntries(_loaderFactory, edmItemCollection)) { foreach (EdmType type in entry.CacheEntry.TypesInAssembly.OfType <EdmType>()) { if (Helper.IsEntityType(type)) { ClrEntityType entityType = (ClrEntityType)type; _cspaceToOspace.Add(_edmItemCollection.GetItem <StructuralType>(entityType.CSpaceTypeName), entityType); } else if (Helper.IsComplexType(type)) { ClrComplexType complexType = (ClrComplexType)type; _cspaceToOspace.Add(_edmItemCollection.GetItem <StructuralType>(complexType.CSpaceTypeName), complexType); } else if (Helper.IsEnumType(type)) { ClrEnumType enumType = (ClrEnumType)type; _cspaceToOspace.Add(_edmItemCollection.GetItem <EnumType>(enumType.CSpaceTypeName), enumType); } else { Debug.Assert(Helper.IsAssociationType(type)); _cspaceToOspace.Add(_edmItemCollection.GetItem <StructuralType>(type.FullName), type); } } } } }
/// <summary> /// Creates new enum OSpace type built based on CLR <paramref name="enumType"/> and <paramref name="cspaceEnumType"/> /// </summary> /// <param name="enumType">CLR type to create OSpace type from.</param> /// <param name="cspaceEnumType">CSpace type used to get namespace and name for the newly created OSpace type.</param> /// <param name="newOSpaceType"> /// New enum OSpace type built based on CLR <paramref name="enumType"/> and <paramref name="cspaceEnumType"/> or null /// if the type could not be built. /// </param> /// <returns><c>true</c> if the type was built successfully.<c>false</c> otherwise.</returns> private bool TryCreateEnumType(Type enumType, EnumType cspaceEnumType, out EdmType newOSpaceType) { Debug.Assert(enumType != null, "enumType != null"); Debug.Assert(enumType.IsEnum, "enum type expected"); Debug.Assert(cspaceEnumType != null, "cspaceEnumType != null"); Debug.Assert(Helper.IsEnumType(cspaceEnumType), "Enum type expected"); Debug.Assert(TypesMatchByConvention(enumType, cspaceEnumType), "The types passed as parameters don't match by convention."); newOSpaceType = null; // Check if the OSpace and CSpace enum type match if (!UnderlyingEnumTypesMatch(enumType, cspaceEnumType) || !EnumMembersMatch(enumType, cspaceEnumType)) { return(false); } newOSpaceType = new ClrEnumType(enumType, cspaceEnumType.NamespaceName, cspaceEnumType.Name); SessionData.TypesInLoading.Add(enumType.FullName, newOSpaceType); return(true); }
/// <summary> /// Load metadata of the given type - when you call this method, you should check and make sure that the type has /// edm attribute. If it doesn't,we won't load the type and it will be returned as null /// </summary> /// <param name="clrType"></param> /// <param name="context"></param> /// <returns></returns> private void LoadType(Type clrType) { Debug.Assert(clrType.Assembly == SourceAssembly, "Why are we loading a type that is not in our assembly?"); Debug.Assert(!SessionData.TypesInLoading.ContainsKey(clrType.FullName), "Trying to load a type that is already loaded???"); Debug.Assert(!clrType.IsGenericType, "Generic type is not supported"); EdmType edmType = null; EdmTypeAttribute[] typeAttributes = (EdmTypeAttribute[])clrType.GetCustomAttributes(typeof(EdmTypeAttribute), false /*inherit*/); // the CLR doesn't allow types to have duplicate/multiple attribute declarations if (typeAttributes.Length != 0) { if (clrType.IsNested) { SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.NestedClassNotSupported(clrType.FullName, clrType.Assembly.FullName), null)); return; } EdmTypeAttribute typeAttribute = typeAttributes[0]; string cspaceTypeName = String.IsNullOrEmpty(typeAttribute.Name) ? clrType.Name : typeAttribute.Name; if (String.IsNullOrEmpty(typeAttribute.NamespaceName) && clrType.Namespace == null) { SessionData.EdmItemErrors.Add(new EdmItemError(Strings.Validator_TypeHasNoNamespace, edmType)); return; } string cspaceNamespaceName = String.IsNullOrEmpty(typeAttribute.NamespaceName) ? clrType.Namespace : typeAttribute.NamespaceName; if (typeAttribute.GetType() == typeof(EdmEntityTypeAttribute)) { edmType = new ClrEntityType(clrType, cspaceNamespaceName, cspaceTypeName); } else if (typeAttribute.GetType() == typeof(EdmComplexTypeAttribute)) { edmType = new ClrComplexType(clrType, cspaceNamespaceName, cspaceTypeName); } else { Debug.Assert(typeAttribute is EdmEnumTypeAttribute, "Invalid type attribute encountered"); // Note that TryGetPrimitiveType() will return false not only for types that are not primitive // but also for CLR primitive types that are valid underlying enum types in CLR but are not // a valid Edm primitive types (e.g. ulong) PrimitiveType underlyingEnumType; if (!ClrProviderManifest.Instance.TryGetPrimitiveType(clrType.GetEnumUnderlyingType(), out underlyingEnumType)) { SessionData.EdmItemErrors.Add( new EdmItemError( Strings.Validator_UnsupportedEnumUnderlyingType(clrType.GetEnumUnderlyingType().FullName), edmType)); return; } edmType = new ClrEnumType(clrType, cspaceNamespaceName, cspaceTypeName); } } else { // not a type we are interested return; } Debug.Assert(!CacheEntry.ContainsType(edmType.Identity), "This type must not be already present in the list of types for this assembly"); // Also add this to the list of the types for this assembly CacheEntry.TypesInAssembly.Add(edmType); // Add this to the known type map so we won't try to load it again SessionData.TypesInLoading.Add(clrType.FullName, edmType); // Load properties for structural type if (Helper.IsStructuralType(edmType)) { //Load base type only for entity type - not sure if we will allow complex type inheritance if (Helper.IsEntityType(edmType)) { TrackClosure(clrType.BaseType); AddTypeResolver( () => edmType.BaseType = ResolveBaseType(clrType.BaseType)); } // Load the properties for this type LoadPropertiesFromType((StructuralType)edmType); } return; }
/// <summary> /// Creates new enum OSpace type built based on CLR <paramref name="enumType"/> and <paramref name="cspaceEnumType"/> /// </summary> /// <param name="enumType">CLR type to create OSpace type from.</param> /// <param name="cspaceEnumType">CSpace type used to get namespace and name for the newly created OSpace type.</param> /// <param name="newOSpaceType"> /// New enum OSpace type built based on CLR <paramref name="enumType"/> and <paramref name="cspaceEnumType"/> or null /// if the type could not be built. /// </param> /// <returns><c>true</c> if the type was built successfully.<c>false</c> otherwise.</returns> private bool TryCreateEnumType(Type enumType, EnumType cspaceEnumType, out EdmType newOSpaceType) { Debug.Assert(enumType != null, "enumType != null"); Debug.Assert(enumType.IsEnum, "enum type expected"); Debug.Assert(cspaceEnumType != null, "cspaceEnumType != null"); Debug.Assert(Helper.IsEnumType(cspaceEnumType), "Enum type expected"); Debug.Assert(TypesMatchByConvention(enumType, cspaceEnumType), "The types passed as parameters don't match by convention."); newOSpaceType = null; // Check if the OSpace and CSpace enum type match if (!UnderlyingEnumTypesMatch(enumType, cspaceEnumType) || !EnumMembersMatch(enumType, cspaceEnumType)) { return false; } newOSpaceType = new ClrEnumType(enumType, cspaceEnumType.NamespaceName, cspaceEnumType.Name); SessionData.TypesInLoading.Add(enumType.FullName, newOSpaceType); return true; }
/// <summary> /// Load metadata of the given type - when you call this method, you should check and make sure that the type has /// edm attribute. If it doesn't,we won't load the type and it will be returned as null /// </summary> /// <param name="clrType"></param> /// <param name="context"></param> /// <returns></returns> private void LoadType(Type clrType) { Debug.Assert(clrType.Assembly == SourceAssembly, "Why are we loading a type that is not in our assembly?"); Debug.Assert(!SessionData.TypesInLoading.ContainsKey(clrType.FullName), "Trying to load a type that is already loaded???"); Debug.Assert(!clrType.IsGenericType, "Generic type is not supported"); EdmType edmType = null; EdmTypeAttribute[] typeAttributes = (EdmTypeAttribute[])clrType.GetCustomAttributes(typeof(EdmTypeAttribute), false /*inherit*/); // the CLR doesn't allow types to have duplicate/multiple attribute declarations if (typeAttributes.Length != 0) { if (clrType.IsNested) { SessionData.EdmItemErrors.Add(new EdmItemError(System.Data.Entity.Strings.NestedClassNotSupported(clrType.FullName, clrType.Assembly.FullName), null)); return; } EdmTypeAttribute typeAttribute = typeAttributes[0]; string cspaceTypeName = String.IsNullOrEmpty(typeAttribute.Name) ? clrType.Name : typeAttribute.Name; if (String.IsNullOrEmpty(typeAttribute.NamespaceName) && clrType.Namespace == null) { SessionData.EdmItemErrors.Add(new EdmItemError(Strings.Validator_TypeHasNoNamespace, edmType)); return; } string cspaceNamespaceName = String.IsNullOrEmpty(typeAttribute.NamespaceName) ? clrType.Namespace : typeAttribute.NamespaceName; if (typeAttribute.GetType() == typeof(EdmEntityTypeAttribute)) { edmType = new ClrEntityType(clrType, cspaceNamespaceName, cspaceTypeName); } else if(typeAttribute.GetType() == typeof(EdmComplexTypeAttribute)) { edmType = new ClrComplexType(clrType, cspaceNamespaceName, cspaceTypeName); } else { Debug.Assert(typeAttribute is EdmEnumTypeAttribute, "Invalid type attribute encountered"); // Note that TryGetPrimitiveType() will return false not only for types that are not primitive // but also for CLR primitive types that are valid underlying enum types in CLR but are not // a valid Edm primitive types (e.g. ulong) PrimitiveType underlyingEnumType; if (!ClrProviderManifest.Instance.TryGetPrimitiveType(clrType.GetEnumUnderlyingType(), out underlyingEnumType)) { SessionData.EdmItemErrors.Add( new EdmItemError( Strings.Validator_UnsupportedEnumUnderlyingType(clrType.GetEnumUnderlyingType().FullName), edmType)); return; } edmType = new ClrEnumType(clrType, cspaceNamespaceName, cspaceTypeName); } } else { // not a type we are interested return; } Debug.Assert(!CacheEntry.ContainsType(edmType.Identity), "This type must not be already present in the list of types for this assembly"); // Also add this to the list of the types for this assembly CacheEntry.TypesInAssembly.Add(edmType); // Add this to the known type map so we won't try to load it again SessionData.TypesInLoading.Add(clrType.FullName, edmType); // Load properties for structural type if (Helper.IsStructuralType(edmType)) { //Load base type only for entity type - not sure if we will allow complex type inheritance if (Helper.IsEntityType(edmType)) { TrackClosure(clrType.BaseType); AddTypeResolver( () => edmType.BaseType = ResolveBaseType(clrType.BaseType)); } // Load the properties for this type LoadPropertiesFromType((StructuralType)edmType); } return; }