示例#1
0
文件: UriHelper.cs 项目: tapika/swupd
        /// <summary>Gets the type name to be used in the URI for the given <paramref name="type"/>.</summary>
        /// <param name="type">Type to get name for.</param>
        /// <param name="context">Data context used to generate type names for types.</param>
        /// <returns>The name for the <paramref name="type"/>, suitable for including in a URI.</returns>
        internal static string GetTypeNameForUri(Type type, DataServiceContext context)
        {
            Debug.Assert(type != null, "type != null");
            Debug.Assert(context != null, "context != null");
            type = Nullable.GetUnderlyingType(type) ?? type;

            PrimitiveType pt;

            if (PrimitiveType.TryGetPrimitiveType(type, out pt))
            {
                if (pt.HasReverseMapping)
                {
                    return(pt.EdmTypeName);
                }
                else
                {
                    // unsupported primitive type
                    throw new NotSupportedException(Strings.ALinq_CantCastToUnsupportedPrimitive(type.Name));
                }
            }
            else
            {
                return(context.ResolveNameFromType(type) ?? type.FullName);
            }
        }
示例#2
0
        internal ClientTypeAnnotation ResolveEdmTypeName(Type expectedType, string edmTypeName)
        {
            ClientTypeAnnotation clientTypeAnnotation;
            PrimitiveType        type;
            string         collectionItemWireTypeName = WebUtil.GetCollectionItemWireTypeName(edmTypeName);
            string         str2  = collectionItemWireTypeName ?? edmTypeName;
            ClientEdmModel model = ClientEdmModel.GetModel(this.ResponseInfo.MaxProtocolVersion);

            if (PrimitiveType.TryGetPrimitiveType(str2, out type))
            {
                clientTypeAnnotation = model.GetClientTypeAnnotation(type.ClrType);
            }
            else if (!this.edmTypeNameMap.TryGetValue(str2, out clientTypeAnnotation))
            {
                clientTypeAnnotation = model.GetClientTypeAnnotation(str2);
            }
            if (collectionItemWireTypeName == null)
            {
                return(clientTypeAnnotation);
            }
            Type elementType = clientTypeAnnotation.ElementType;

            if (type != null)
            {
                elementType = ClientTypeUtil.GetImplementationType(expectedType, typeof(ICollection <>)).GetGenericArguments()[0];
            }
            Type backingTypeForCollectionProperty = WebUtil.GetBackingTypeForCollectionProperty(expectedType, elementType);

            return(model.GetClientTypeAnnotation(backingTypeForCollectionProperty));
        }
示例#3
0
        /// <summary>
        /// convert from string to the appropriate type
        /// </summary>
        /// <param name="propertyValue">incoming string value</param>
        /// <param name="propertyType">type to convert to</param>
        /// <returns>converted value</returns>
        internal static object ChangeType(string propertyValue, Type propertyType)
        {
            Debug.Assert(null != propertyValue, "should never be passed null");

            PrimitiveType primitiveType;

            if (PrimitiveType.TryGetPrimitiveType(propertyType, out primitiveType) && primitiveType.TypeConverter != null)
            {
                try
                {
                    // functionality provided by type converter
                    return(primitiveType.TypeConverter.Parse(propertyValue));
                }
                catch (FormatException ex)
                {
                    propertyValue = (0 == propertyValue.Length ? "String.Empty" : "String");
                    throw Error.InvalidOperation(Strings.Deserialize_Current(propertyType.ToString(), propertyValue), ex);
                }
                catch (OverflowException ex)
                {
                    propertyValue = (0 == propertyValue.Length ? "String.Empty" : "String");
                    throw Error.InvalidOperation(Strings.Deserialize_Current(propertyType.ToString(), propertyValue), ex);
                }
            }
            else
            {
                Debug.Assert(false, "new StorageType without update to knownTypes");
                return(propertyValue);
            }
        }
示例#4
0
        /// <summary>type edm type string for content</summary>
        /// <param name="propertyType">type to analyze</param>
        /// <returns>edm type string for payload, null for unknown</returns>
        internal static string GetEdmType(Type propertyType)
        {
            PrimitiveType primitiveType;

            if (PrimitiveType.TryGetPrimitiveType(propertyType, out primitiveType))
            {
                if (primitiveType.EdmTypeName != null)
                {
                    return(primitiveType.EdmTypeName);
                }
                else
                {
                    // case StorageType.UInt16:
                    // case StorageType.UInt32:
                    // case StorageType.UInt64:
                    // don't support reverse mappings for these types in this version
                    // allows us to add real server support in the future without a
                    // "breaking change" in the future client
                    throw new NotSupportedException(Strings.ALinq_CantCastToUnsupportedPrimitive(propertyType.Name));
                }
            }
            else
            {
                Debug.Assert(false, "knowntype without reverse mapping");
                return(null);
            }
        }
示例#5
0
        internal static string ToString(object propertyValue)
        {
            PrimitiveType type;

            if (PrimitiveType.TryGetPrimitiveType(propertyValue.GetType(), out type) && (type.TypeConverter != null))
            {
                return(type.TypeConverter.ToString(propertyValue));
            }
            return(propertyValue.ToString());
        }
示例#6
0
        /// <summary>
        /// Returns the primitive property value.
        /// </summary>
        /// <param name="propertyValue">Value of the property.</param>
        /// <param name="propertyType">Type of the property.</param>
        /// <returns>Returns the value of the primitive property.</returns>
        private static object ConvertPrimitiveValueToRecognizedODataType(object propertyValue, Type propertyType)
        {
            Debug.Assert(PrimitiveType.IsKnownNullableType(propertyType), "GetPrimitiveValue must be called only for primitive types");
            Debug.Assert(propertyValue == null || PrimitiveType.IsKnownType(propertyValue.GetType()), "GetPrimitiveValue method must be called for primitive values only");

            if (propertyValue == null)
            {
                return(null);
            }

            PrimitiveType primitiveType;

            PrimitiveType.TryGetPrimitiveType(propertyType, out primitiveType);
            Debug.Assert(primitiveType != null, "must be a known primitive type");

            // Do the conversion for types that are not supported by ODataLib e.g. char[], char, etc
            if (propertyType == typeof(Char) ||
                propertyType == typeof(Char[]) ||
                propertyType == typeof(Type) ||
                propertyType == typeof(Uri) ||
                propertyType == typeof(Xml.Linq.XDocument) ||
                propertyType == typeof(Xml.Linq.XElement))
            {
                return(primitiveType.TypeConverter.ToString(propertyValue));
            }
#if !ASTORIA_LIGHT && !PORTABLELIB
            else if (propertyType.FullName == "System.Data.Linq.Binary")
            {
                // For System.Data.Linq.Binary, it is a delay loaded type. Hence checking it based on name.
                // PrimitiveType.IsKnownType checks for binary type based on name and assembly. Hence just
                // checking name here is sufficient, since any other type with the same name, but in different
                // assembly will return false for PrimitiveType.IsKnownNullableType.
                // Since ODataLib does not understand binary type, we need to convert the value to byte[].
                return(((BinaryTypeConverter)primitiveType.TypeConverter).ToArray(propertyValue));
            }
#endif
            else if (primitiveType.EdmTypeName == null)
            {
                // case StorageType.DateTimeOffset:
                // case StorageType.TimeSpan:
                // case StorageType.UInt16:
                // case StorageType.UInt32:
                // case StorageType.UInt64:
                // don't support reverse mappings for these types in this version
                // allows us to add real server support in the future without a
                // "breaking change" in the future client
                throw new NotSupportedException(Strings.ALinq_CantCastToUnsupportedPrimitive(propertyType.Name));
            }

            return(propertyValue);
        }
示例#7
0
        /// <summary>
        /// Resolves the client type that should be used for materialization.
        /// </summary>
        /// <param name="expectedType">Expected client clr type based on the API called.</param>
        /// <param name="readerTypeName">
        /// The name surfaced by the ODataLib reader.
        /// If we have a server model, this will be a server type name that needs to be resolved.
        /// If not, then this will already be a client type name.</param>
        /// <returns>The resolved annotation for the client type to materialize into.</returns>
        internal ClientTypeAnnotation ResolveTypeForMaterialization(Type expectedType, string readerTypeName)
        {
            // If its a collection, get the collection item name
            string collectionItemTypeName = WebUtil.GetCollectionItemWireTypeName(readerTypeName);

            if (collectionItemTypeName == null)
            {
                // Resolve the primitive type first
                PrimitiveType primitiveType;
                if (PrimitiveType.TryGetPrimitiveType(readerTypeName, out primitiveType))
                {
                    return(this.clientEdmModel.GetClientTypeAnnotation(primitiveType.ClrType));
                }

                ClientTypeAnnotation resultType;
                if (this.edmTypeNameMap.TryGetValue(readerTypeName, out resultType))
                {
                    return(resultType);
                }

                if (this.serviceModel != null)
                {
                    var resolvedType = this.ResolveTypeFromName(readerTypeName, expectedType);
                    return(this.clientEdmModel.GetClientTypeAnnotation(resolvedType));
                }

                // If there was no type name specified in the payload, then the type resolver won't be invoked
                // and hence that edm type name might not be in the resolver cache. Hence look that up in the
                // ClientEdmModel cache. This lookup is more expensive and is unique across the app domain for the
                // given version.
                return(this.clientEdmModel.GetClientTypeAnnotation(readerTypeName));
            }

            Type collectionImplementationType = ClientTypeUtil.GetImplementationType(expectedType, typeof(ICollection <>));
            Type collectionElementType        = collectionImplementationType.GetGenericArguments()[0];

            // In case of collection, the expectedType might be collection of nullable types (for e.g. ICollection<int?>).
            // There is no way to know the nullability from the wireTypeName (For e.g. Collection(Edm.Int32)).
            // Hence in case of collections of primitives, we need to look at the element type of the expected type
            // and use that to create the instance otherwise we will not be able to assign the created ICollection<>
            // instance to the property on the user's entity (ICollection<int> cannot be assigned to ICollection<int?>).
            // There is also no need to invoke the resolver for primitives, so we just use the element type.
            if (!PrimitiveType.IsKnownType(collectionElementType))
            {
                collectionElementType = this.ResolveTypeForMaterialization(collectionElementType, collectionItemTypeName).ElementType;
            }

            Type clrCollectionType = WebUtil.GetBackingTypeForCollectionProperty(expectedType, collectionElementType);

            return(this.clientEdmModel.GetClientTypeAnnotation(clrCollectionType));
        }
示例#8
0
        /// <summary>
        /// Convert from primitive value to an xml payload string.
        /// NOTE: We need to pay special attention to DateTimes - if the converted value is going to be used as a content of
        /// atom:updated or atom:published element we have to ensure it contains information about time zone. At the same time we
        /// must not touch datetime values that in content or are mapped to custom elements.
        /// </summary>
        /// <param name="propertyValue">incoming object value</param>
        /// <returns>converted value</returns>
        internal static string ToString(object propertyValue)
        {
            Debug.Assert(null != propertyValue, "null should be handled by caller");

            PrimitiveType primitiveType;

            if (PrimitiveType.TryGetPrimitiveType(propertyValue.GetType(), out primitiveType) && primitiveType.TypeConverter != null)
            {
                return(primitiveType.TypeConverter.ToString(propertyValue));
            }

            Debug.Assert(false, "new StorageType without update to knownTypes");
            return(propertyValue.ToString());
        }
示例#9
0
        internal static string GetEdmType(Type propertyType)
        {
            PrimitiveType type;

            if (!PrimitiveType.TryGetPrimitiveType(propertyType, out type))
            {
                return(null);
            }
            if (type.EdmTypeName == null)
            {
                throw new NotSupportedException(Strings.ALinq_CantCastToUnsupportedPrimitive(propertyType.Name));
            }
            return(type.EdmTypeName);
        }
示例#10
0
        internal static string GetTypeNameForUri(Type type, DataServiceContext context)
        {
            PrimitiveType type2;

            type = Nullable.GetUnderlyingType(type) ?? type;
            if (PrimitiveType.TryGetPrimitiveType(type, out type2))
            {
                if (!type2.HasReverseMapping)
                {
                    throw new NotSupportedException(Strings.ALinq_CantCastToUnsupportedPrimitive(type.Name));
                }
                return(type2.EdmTypeName);
            }
            return(context.ResolveNameFromType(type) ?? type.FullName);
        }
示例#11
0
        internal static bool ToNamedType(string typeName, out Type type)
        {
            PrimitiveType type2;

            type = typeof(string);
            if (string.IsNullOrEmpty(typeName))
            {
                return(true);
            }
            if (PrimitiveType.TryGetPrimitiveType(typeName, out type2))
            {
                type = type2.ClrType;
                return(true);
            }
            return(false);
        }
示例#12
0
        internal static bool TryConvertBinaryToByteArray(object binaryValue, out byte[] converted)
        {
            Debug.Assert(binaryValue != null, "binaryValue != null");
#if !ASTORIA_LIGHT && !PORTABLELIB
            Type          valueType = binaryValue.GetType();
            PrimitiveType ptype;
            if (PrimitiveType.TryGetPrimitiveType(valueType, out ptype) && valueType == BinaryTypeConverter.BinaryType)
            {
                const BindingFlags Flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod;
                converted = (byte[])valueType.InvokeMember("ToArray", Flags, null, binaryValue, null, CultureInfo.InvariantCulture);
                return(true);
            }
#endif
            converted = null;
            return(false);
        }
示例#13
0
        private ODataCollectionValue CreateODataCollection(Type collectionItemType, string propertyName, object value, List <object> visitedComplexTypeObjects)
        {
            PrimitiveType                    type;
            string                           edmType;
            Func <object, object>            valueConverter = null;
            Func <object, ODataComplexValue> func2          = null;

            WebUtil.ValidateCollection(collectionItemType, value, propertyName);
            bool flag = PrimitiveType.TryGetPrimitiveType(collectionItemType, out type);
            ODataCollectionValue value2     = new ODataCollectionValue();
            IEnumerable          enumerable = (IEnumerable)value;

            if (flag)
            {
                edmType = ClientConvert.GetEdmType(Nullable.GetUnderlyingType(collectionItemType) ?? collectionItemType);
                if (valueConverter == null)
                {
                    valueConverter = delegate(object val) {
                        WebUtil.ValidateCollectionItem(val);
                        WebUtil.ValidatePrimitiveCollectionItem(val, propertyName, collectionItemType);
                        return(GetPrimitiveValue(val, collectionItemType));
                    };
                }
                value2.Items = Util.GetEnumerable <object>(enumerable, valueConverter);
            }
            else
            {
                edmType = this.requestInfo.ResolveNameFromType(collectionItemType);
                if (func2 == null)
                {
                    func2 = delegate(object val) {
                        WebUtil.ValidateCollectionItem(val);
                        WebUtil.ValidateComplexCollectionItem(val, propertyName, collectionItemType);
                        return(this.CreateODataComplexValue(collectionItemType, val, propertyName, true, visitedComplexTypeObjects));
                    };
                }
                value2.Items = Util.GetEnumerable <ODataComplexValue>(enumerable, func2);
            }
            string str2 = (edmType == null) ? null : string.Format(CultureInfo.InvariantCulture, "Collection({0})", new object[] { edmType });
            SerializationTypeNameAnnotation annotation = new SerializationTypeNameAnnotation {
                TypeName = str2
            };

            value2.SetAnnotation <SerializationTypeNameAnnotation>(annotation);
            return(value2);
        }
示例#14
0
 /// <summary>
 /// change primtive typeName into non-nullable type
 /// </summary>
 /// <param name="typeName">like Edm.String or Edm.Binary</param>
 /// <param name="type">the mapped output type</param>
 /// <returns>true if named</returns>
 internal static bool ToNamedType(string typeName, out Type type)
 {
     type = typeof(string);
     if (String.IsNullOrEmpty(typeName))
     {
         return(true);
     }
     else
     {
         PrimitiveType ptype;
         if (PrimitiveType.TryGetPrimitiveType(typeName, out ptype))
         {
             type = ptype.ClrType;
             return(true);
         }
         else
         {
             return(false);
         }
     }
 }
示例#15
0
        private static object GetPrimitiveValue(object propertyValue, Type propertyType)
        {
            PrimitiveType type;

            if (propertyValue == null)
            {
                return(null);
            }
            PrimitiveType.TryGetPrimitiveType(propertyType, out type);
            if ((((propertyType == typeof(char)) || (propertyType == typeof(char[]))) || ((propertyType == typeof(Type)) || (propertyType == typeof(Uri)))) || ((propertyType == typeof(XDocument)) || (propertyType == typeof(XElement))))
            {
                return(type.TypeConverter.ToString(propertyValue));
            }
            if (propertyType.FullName == "System.Data.Linq.Binary")
            {
                return(((BinaryTypeConverter)type.TypeConverter).ToArray(propertyValue));
            }
            if (type.EdmTypeName == null)
            {
                throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_CantCastToUnsupportedPrimitive(propertyType.Name));
            }
            return(propertyValue);
        }
示例#16
0
        internal static object ChangeType(string propertyValue, Type propertyType)
        {
            PrimitiveType type;

            if (PrimitiveType.TryGetPrimitiveType(propertyType, out type) && (type.TypeConverter != null))
            {
                try
                {
                    return(type.TypeConverter.Parse(propertyValue));
                }
                catch (FormatException exception)
                {
                    propertyValue = (propertyValue.Length == 0) ? "String.Empty" : "String";
                    throw Error.InvalidOperation(Strings.Deserialize_Current(propertyType.ToString(), propertyValue), exception);
                }
                catch (OverflowException exception2)
                {
                    propertyValue = (propertyValue.Length == 0) ? "String.Empty" : "String";
                    throw Error.InvalidOperation(Strings.Deserialize_Current(propertyType.ToString(), propertyValue), exception2);
                }
            }
            return(propertyValue);
        }
示例#17
0
        /// <summary>
        /// Creates and returns an ODataCollectionValue from the given value.
        /// </summary>
        /// <param name="collectionItemType">The type of the value.</param>
        /// <param name="propertyName">If the value is a property, then it represents the name of the property. Can be null, for non-property.</param>
        /// <param name="value">The value.</param>
        /// <param name="visitedComplexTypeObjects">Set of instances of complex types encountered in the hierarchy. Used to detect cycles.</param>
        /// <returns>An ODataCollectionValue representing the given value.</returns>
        internal ODataCollectionValue CreateODataCollection(Type collectionItemType, string propertyName, object value, HashSet <object> visitedComplexTypeObjects)
        {
            Debug.Assert(collectionItemType != null, "collectionItemType != null");

            WebUtil.ValidateCollection(collectionItemType, value, propertyName);

            PrimitiveType ptype;
            bool          isCollectionOfPrimitiveTypes = PrimitiveType.TryGetPrimitiveType(collectionItemType, out ptype);

            ODataCollectionValue collection = new ODataCollectionValue();
            IEnumerable          enumerablePropertyValue = (IEnumerable)value;
            string collectionItemTypeName;
            string collectionTypeName;

            if (isCollectionOfPrimitiveTypes)
            {
                collectionItemTypeName = ClientConvert.GetEdmType(Nullable.GetUnderlyingType(collectionItemType) ?? collectionItemType);

                collection.Items = Util.GetEnumerable(
                    enumerablePropertyValue,
                    (val) =>
                {
                    WebUtil.ValidateCollectionItem(val);
                    WebUtil.ValidatePrimitiveCollectionItem(val, propertyName, collectionItemType);
                    return(ConvertPrimitiveValueToRecognizedODataType(val, collectionItemType));
                });

                // TypeName for primitives should be the EDM name since that's what we will be able to look up in the model
                collectionTypeName = collectionItemTypeName;
            }
            else
            {
                // Note that the collectionItemTypeName will be null if the context does not have the ResolveName func.
                collectionItemTypeName = this.requestInfo.ResolveNameFromType(collectionItemType);
                collection.Items       = Util.GetEnumerable(
                    enumerablePropertyValue,
                    (val) =>
                {
                    WebUtil.ValidateCollectionItem(val);
                    WebUtil.ValidateComplexCollectionItem(val, propertyName, collectionItemType);
                    return(this.CreateODataComplexValue(collectionItemType, val, propertyName, true /*isCollectionItem*/, visitedComplexTypeObjects));
                });

                // TypeName for complex types needs to be the client type name (not the one we resolved above) since it will be looked up in the client model
                collectionTypeName = collectionItemType.FullName;
            }

            // Set the type name to use for client type lookups and validation. Because setting this value can cause validation to occur, we will
            // only do it for JSON Light, in order to avoid breaking changes with the WCF Data Services 5.0 release, since it was already shipped without this.
            if (!this.requestInfo.Format.UsingAtom)
            {
                collection.TypeName = GetCollectionName(collectionTypeName);
            }

            string wireTypeName = GetCollectionName(collectionItemTypeName);

            collection.SetAnnotation(new SerializationTypeNameAnnotation {
                TypeName = wireTypeName
            });
            return(collection);
        }
示例#18
0
        private EdmTypeCacheValue GetOrCreateEdmTypeInternal(IEdmStructuredType edmBaseType, Type type, PropertyInfo[] keyProperties, bool isEntity, bool?hasProperties)
        {
            EdmTypeCacheValue value2;
            Action <MetadataProviderEdmEntityType>  action3 = null;
            Action <MetadataProviderEdmComplexType> action4 = null;

            lock (this.clrToEdmTypeCache)
            {
                this.clrToEdmTypeCache.TryGetValue(type, out value2);
            }
            if (value2 == null)
            {
                if (PrimitiveType.IsKnownNullableType(type))
                {
                    PrimitiveType type3;
                    PrimitiveType.TryGetPrimitiveType(type, out type3);
                    value2 = new EdmTypeCacheValue(type3.CreateEdmPrimitiveType(), hasProperties);
                }
                else
                {
                    Type type2;
                    if (((type2 = ClientTypeUtil.GetImplementationType(type, typeof(ICollection <>))) != null) && (ClientTypeUtil.GetImplementationType(type, typeof(IDictionary <,>)) == null))
                    {
                        Type type4 = type2.GetGenericArguments()[0];
                        value2 = new EdmTypeCacheValue(new EdmCollectionType(this.GetOrCreateEdmTypeInternal(type4).EdmType.ToEdmTypeReference(ClientTypeUtil.CanAssignNull(type4))), hasProperties);
                    }
                    else if (isEntity)
                    {
                        if (action3 == null)
                        {
                            action3 = delegate(MetadataProviderEdmEntityType entityType) {
                                List <IEdmProperty>           list  = new List <IEdmProperty>();
                                List <IEdmStructuralProperty> list1 = new List <IEdmStructuralProperty>();
                                using (IEnumerator <PropertyInfo> enumerator = (from p in ClientTypeUtil.GetPropertiesOnType(type, edmBaseType != null)
                                                                                orderby p.Name
                                                                                select p).GetEnumerator())
                                {
                                    Func <PropertyInfo, bool> predicate = null;
                                    while (enumerator.MoveNext())
                                    {
                                        PropertyInfo property = enumerator.Current;
                                        IEdmProperty item     = this.CreateEdmProperty(entityType, property);
                                        list.Add(item);
                                        if (edmBaseType == null)
                                        {
                                            if (predicate == null)
                                            {
                                                predicate = k => (k.DeclaringType == type) && (k.Name == property.Name);
                                            }
                                            if (keyProperties.Any <PropertyInfo>(predicate))
                                            {
                                                list1.Add((IEdmStructuralProperty)item);
                                            }
                                        }
                                    }
                                }
                                foreach (IEdmProperty property2 in list)
                                {
                                    entityType.AddProperty(property2);
                                }
                                entityType.AddKeys(list1);
                            };
                        }
                        Action <MetadataProviderEdmEntityType> propertyLoadAction = action3;
                        value2 = new EdmTypeCacheValue(new MetadataProviderEdmEntityType(CommonUtil.GetModelTypeNamespace(type), CommonUtil.GetModelTypeName(type), (IEdmEntityType)edmBaseType, type.IsAbstract(), false, propertyLoadAction), hasProperties);
                    }
                    else
                    {
                        if (action4 == null)
                        {
                            action4 = delegate(MetadataProviderEdmComplexType complexType) {
                                List <IEdmProperty> list = new List <IEdmProperty>();
                                foreach (PropertyInfo info in from p in ClientTypeUtil.GetPropertiesOnType(type, edmBaseType != null)
                                         orderby p.Name
                                         select p)
                                {
                                    IEdmProperty item = this.CreateEdmProperty(complexType, info);
                                    list.Add(item);
                                }
                                foreach (IEdmProperty property2 in list)
                                {
                                    complexType.AddProperty(property2);
                                }
                            };
                        }
                        Action <MetadataProviderEdmComplexType> action2 = action4;
                        value2 = new EdmTypeCacheValue(new MetadataProviderEdmComplexType(CommonUtil.GetModelTypeNamespace(type), CommonUtil.GetModelTypeName(type), (IEdmComplexType)edmBaseType, type.IsAbstract(), action2), hasProperties);
                    }
                }
                IEdmType             edmType = value2.EdmType;
                ClientTypeAnnotation orCreateClientTypeAnnotation = this.GetOrCreateClientTypeAnnotation(edmType, type);
                edmType.SetClientTypeAnnotation(orCreateClientTypeAnnotation);
                if ((edmType.TypeKind == EdmTypeKind.Entity) || (edmType.TypeKind == EdmTypeKind.Complex))
                {
                    IEdmStructuredType edmStructuredType = edmType as IEdmStructuredType;
                    this.SetMimeTypeForProperties(edmStructuredType);
                }
                lock (this.clrToEdmTypeCache)
                {
                    EdmTypeCacheValue value3;
                    if (this.clrToEdmTypeCache.TryGetValue(type, out value3))
                    {
                        return(value3);
                    }
                    this.clrToEdmTypeCache.Add(type, value2);
                }
            }
            return(value2);
        }
示例#19
0
        private EdmTypeCacheValue GetOrCreateEdmTypeInternal(IEdmStructuredType edmBaseType, Type type, PropertyInfo[] keyProperties, bool isEntity, bool?hasProperties)
        {
            Debug.Assert(type != null, "type != null");
            Debug.Assert(keyProperties != null, "keyProperties != null");

            EdmTypeCacheValue cachedEdmType;

            lock (this.clrToEdmTypeCache)
            {
                this.clrToEdmTypeCache.TryGetValue(type, out cachedEdmType);
            }

            if (cachedEdmType == null)
            {
                Type collectionType;
                if (PrimitiveType.IsKnownNullableType(type))
                {
                    PrimitiveType primitiveType;
                    PrimitiveType.TryGetPrimitiveType(type, out primitiveType);
                    Debug.Assert(primitiveType != null, "primitiveType != null");
                    cachedEdmType = new EdmTypeCacheValue(primitiveType.CreateEdmPrimitiveType(), hasProperties);
                }
                else if ((collectionType = ClientTypeUtil.GetImplementationType(type, typeof(ICollection <>))) != null && ClientTypeUtil.GetImplementationType(type, typeof(IDictionary <,>)) == null)
                {
                    // Collection Type
                    Type     elementType = collectionType.GetGenericArguments()[0];
                    IEdmType itemType    = this.GetOrCreateEdmTypeInternal(elementType).EdmType;

                    // Note that while collection of a collection is not allowed, we cannot throw here since it's a breaking change.
                    // We will throw during SaveChanges() and we have unit test validating the error case.
                    Debug.Assert(
                        itemType.TypeKind == EdmTypeKind.Entity || itemType.TypeKind == EdmTypeKind.Complex || itemType.TypeKind == EdmTypeKind.Primitive || itemType.TypeKind == EdmTypeKind.Collection,
                        "itemType.TypeKind == EdmTypeKind.Entity || itemType.TypeKind == EdmTypeKind.Complex || itemType.TypeKind == EdmTypeKind.Primitive || itemType.TypeKind == EdmTypeKind.Collection");

                    cachedEdmType = new EdmTypeCacheValue(new EdmCollectionType(itemType.ToEdmTypeReference(ClientTypeUtil.CanAssignNull(elementType))), hasProperties);
                }
                else
                {
                    if (isEntity)
                    {
                        Action <EdmEntityTypeWithDelayLoadedProperties> delayLoadEntityProperties = (entityType) =>
                        {
                            // Create properties without modifying the entityType.
                            // This will leave entityType intact in case of an exception during loading.
                            List <IEdmProperty>           loadedProperties    = new List <IEdmProperty>();
                            List <IEdmStructuralProperty> loadedKeyProperties = new List <IEdmStructuralProperty>();
                            foreach (PropertyInfo property in ClientTypeUtil.GetPropertiesOnType(type, /*declaredOnly*/ edmBaseType != null).OrderBy(p => p.Name))
                            {
                                IEdmProperty edmProperty = this.CreateEdmProperty((EdmStructuredType)entityType, property);
                                loadedProperties.Add(edmProperty);

                                if (edmBaseType == null && keyProperties.Any(k => k.DeclaringType == type && k.Name == property.Name))
                                {
                                    Debug.Assert(edmProperty.PropertyKind == EdmPropertyKind.Structural, "edmProperty.PropertyKind == EdmPropertyKind.Structural");
                                    Debug.Assert(edmProperty.Type.TypeKind() == EdmTypeKind.Primitive, "edmProperty.Type.TypeKind() == EdmTypeKind.Primitive");
                                    loadedKeyProperties.Add((IEdmStructuralProperty)edmProperty);
                                }
                            }

                            // Now add properties to the entityType.
                            foreach (IEdmProperty property in loadedProperties)
                            {
                                entityType.AddProperty(property);
                            }

                            entityType.AddKeys(loadedKeyProperties);
                        };

                        // Creating an entity type
                        Debug.Assert(edmBaseType == null || edmBaseType.TypeKind == EdmTypeKind.Entity, "baseType == null || baseType.TypeKind == EdmTypeKind.Entity");
                        cachedEdmType = new EdmTypeCacheValue(
                            new EdmEntityTypeWithDelayLoadedProperties(CommonUtil.GetModelTypeNamespace(type), CommonUtil.GetModelTypeName(type), (IEdmEntityType)edmBaseType, c.PlatformHelper.IsAbstract(type), false /*isOpen*/, delayLoadEntityProperties),
                            hasProperties);
                    }
                    else
                    {
                        Action <EdmComplexTypeWithDelayLoadedProperties> delayLoadComplexProperties = (complexType) =>
                        {
                            // Create properties without modifying the complexType.
                            // This will leave complexType intact in case of an exception during loading.
                            List <IEdmProperty> loadedProperties = new List <IEdmProperty>();
                            foreach (PropertyInfo property in ClientTypeUtil.GetPropertiesOnType(type, /*declaredOnly*/ edmBaseType != null).OrderBy(p => p.Name))
                            {
                                IEdmProperty edmProperty = this.CreateEdmProperty(complexType, property);
                                loadedProperties.Add(edmProperty);
                            }

                            // Now add properties to the complexType.
                            foreach (IEdmProperty property in loadedProperties)
                            {
                                complexType.AddProperty(property);
                            }
                        };

                        // Creating a complex type
                        Debug.Assert(edmBaseType == null || edmBaseType.TypeKind == EdmTypeKind.Complex, "baseType == null || baseType.TypeKind == EdmTypeKind.Complex");
                        cachedEdmType = new EdmTypeCacheValue(
                            new EdmComplexTypeWithDelayLoadedProperties(CommonUtil.GetModelTypeNamespace(type), CommonUtil.GetModelTypeName(type), (IEdmComplexType)edmBaseType, c.PlatformHelper.IsAbstract(type), delayLoadComplexProperties),
                            hasProperties);
                    }
                }

                Debug.Assert(cachedEdmType != null, "cachedEdmType != null");

                IEdmType             edmType = cachedEdmType.EdmType;
                ClientTypeAnnotation clientTypeAnnotation = this.GetOrCreateClientTypeAnnotation(edmType, type);
                this.SetClientTypeAnnotation(edmType, clientTypeAnnotation);

                if (edmType.TypeKind == EdmTypeKind.Entity || edmType.TypeKind == EdmTypeKind.Complex)
                {
                    IEdmStructuredType edmStructuredType = edmType as IEdmStructuredType;
                    Debug.Assert(edmStructuredType != null, "edmStructuredType != null");
                    this.SetMimeTypeForProperties(edmStructuredType);
                }

                // Need to cache the type before loading the properties so we don't stack overflow because
                // loading the property can trigger calls to GetOrCreateEdmType on the same type.
                lock (this.clrToEdmTypeCache)
                {
                    EdmTypeCacheValue existing;
                    if (this.clrToEdmTypeCache.TryGetValue(type, out existing))
                    {
                        cachedEdmType = existing;
                    }
                    else
                    {
                        this.clrToEdmTypeCache.Add(type, cachedEdmType);
                    }
                }
            }

            return(cachedEdmType);
        }
示例#20
0
        internal static bool IsBinaryValue(object value)
        {
            PrimitiveType type;

            return(PrimitiveType.TryGetPrimitiveType(value.GetType(), out type) && (value.GetType() == BinaryTypeConverter.BinaryType));
        }