/// <summary> /// Get or create a client EDM type instance. /// </summary> /// <param name="type">type to wrap</param> /// <returns>client type</returns> private EdmTypeCacheValue GetOrCreateEdmTypeInternal(Type type) { Debug.Assert(type != null, "type != null"); EdmTypeCacheValue cachedEdmType; lock (this.clrToEdmTypeCache) { this.clrToEdmTypeCache.TryGetValue(type, out cachedEdmType); } if (cachedEdmType == null) { if (PrimitiveType.IsKnownNullableType(type)) { cachedEdmType = this.GetOrCreateEdmTypeInternal(null /*baseType*/, type, ClientTypeUtil.EmptyPropertyInfoArray, false /*isEntity*/, false /*hasProperties*/); } else { PropertyInfo[] keyProperties; bool hasProperties; Type[] hierarchy = ClientEdmModel.GetTypeHierarchy(type, out keyProperties, out hasProperties); Debug.Assert(keyProperties == null || keyProperties.Length == 0 || keyProperties.All(p => p.DeclaringType == keyProperties[0].DeclaringType), "All key properties must be declared on the same type."); bool isEntity = keyProperties != null; keyProperties = keyProperties ?? ClientTypeUtil.EmptyPropertyInfoArray; foreach (Type t in hierarchy) { // Pass in the full list of key properties for the most base type to be added there. We only allow key properties to be // declared on the same type. IEdmStructuredType edmBaseType = cachedEdmType == null ? null : cachedEdmType.EdmType as IEdmStructuredType; cachedEdmType = this.GetOrCreateEdmTypeInternal(edmBaseType, t, keyProperties, isEntity, t == type ? hasProperties : (bool?)null); // Pass in an empty PropertyInfo array on subsequent derived types. keyProperties = ClientTypeUtil.EmptyPropertyInfoArray; } } } Debug.Assert(cachedEdmType != null, "cachedEdmType != null"); return(cachedEdmType); }