#pragma warning restore 649 #endif #endregion Private fields. /// <summary> /// constructor /// </summary> /// <param name="context">originating context</param> /// <param name="reader">reader</param> /// <param name="queryComponents">Query components (projection, expected type)</param> /// <param name="plan">Projection plan (if compiled in an earlier query).</param> /// <param name="mergeOption">merge option to use for this materialization pass</param> internal MaterializeAtom(DataServiceContext context, XmlReader reader, QueryComponents queryComponents, ProjectionPlan plan, MergeOption mergeOption) { Debug.Assert(queryComponents != null, "queryComponents != null"); this.context = context; this.elementType = queryComponents.LastSegmentType; this.MergeOptionValue = mergeOption; this.ignoreMissingProperties = context.IgnoreMissingProperties; this.reader = (reader == null) ? null : new System.Data.Services.Client.Xml.XmlAtomErrorReader(reader); this.countValue = CountStateInitial; this.expectingSingleValue = ClientConvert.IsKnownNullableType(elementType); Debug.Assert(reader != null, "Materializer reader is null! Did you mean to use Materializer.ResultsWrapper/EmptyResults?"); // NOTE: dataNamespace is used for reference equality, and while it looks like // a variable, it appears that it will only get set to XmlConstants.DataWebNamespace // at runtime. Therefore we remove string dataNamespace as a field here. // this.dataNamespace = reader != null ? reader.Settings.NameTable.Add(context.DataNamespace) : null; reader.Settings.NameTable.Add(context.DataNamespace); string typeScheme = this.context.TypeScheme.OriginalString; this.parser = new AtomParser(this.reader, AtomParser.XElementBuilderCallback, typeScheme, context.DataNamespace); AtomMaterializerLog log = new AtomMaterializerLog(this.context, mergeOption); Type implementationType; Type materializerType = GetTypeForMaterializer(this.expectingSingleValue, this.elementType, out implementationType); this.materializer = new AtomMaterializer(parser, context, materializerType, this.ignoreMissingProperties, mergeOption, log, this.MaterializedObjectCallback, queryComponents, plan); }
internal override Expression VisitUnary(UnaryExpression u) { Debug.Assert(u != null, "u != null"); // Perfectly assignable conversions are OK. VB.NET compilers // inserts these to exactly match method signatures, for example. if (ResourceBinder.PatternRules.MatchConvertToAssignable(u)) { return(base.VisitUnary(u)); } if ((u.NodeType == ExpressionType.Convert) || (u.NodeType == ExpressionType.ConvertChecked)) { Type sourceType = Nullable.GetUnderlyingType(u.Operand.Type) ?? u.Operand.Type; Type targetType = Nullable.GetUnderlyingType(u.Type) ?? u.Type; // when projecting known entity types, will allow convert expressions of primitive types. if (ClientConvert.IsKnownType(sourceType) && ClientConvert.IsKnownType(targetType)) { return(base.Visit(u.Operand)); } } throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, u.ToString())); }
/// <summary> /// CODE: x /// ORIGINAL: Convert(x, t) where t is assignable from typeof(x) /// ORIGINAL: x as t, where t is assignable from typeof(x) /// ORIGINAL: and typeof(x) or t are not known primitives unless typeof(x) == t /// ORIGINAL: and x is not a collection of entity types /// NORMALIZED: x /// </summary> internal override Expression VisitUnary(UnaryExpression u) { UnaryExpression visited = (UnaryExpression)base.VisitUnary(u); Expression result = visited; // Note that typically we would record a potential rewrite // after extracting the conversion, but we avoid doing this // because it breaks undoing the rewrite by making the non-local // change circular, ie: // unary [operand = a] // becomes // a <- unary [operand = a] // So the undoing visits a, then the original unary, then the // operand and again the unary, the operand, etc. this.RecordRewrite(u, result); // Convert(x, t) or x as t, where t is assignable from typeof(x) if ((visited.NodeType == ExpressionType.Convert || visited.NodeType == ExpressionType.TypeAs) && visited.Type.IsAssignableFrom(visited.Operand.Type)) { // typeof(x) or t are not known primitives unless typeof(x) == t if (!ClientConvert.IsKnownNullableType(visited.Operand.Type) && !ClientConvert.IsKnownNullableType(visited.Type) || visited.Operand.Type == visited.Type) { // x is not a collection of entity types if (!(ClientType.CheckElementTypeIsEntity(visited.Operand.Type) && ProjectionAnalyzer.IsCollectionProducingExpression(visited.Operand))) { result = visited.Operand; } } } return(result); }
internal override Expression VisitMemberAccess(MemberExpression m) { Debug.Assert(m != null, "m != null"); Expression result; Expression baseSourceExpression = m.Expression; if (ClientConvert.IsKnownNullableType(baseSourceExpression.Type)) { result = base.VisitMemberAccess(m); } else { Expression baseTargetExpression = this.Visit(baseSourceExpression); ExpressionAnnotation annotation; if (this.annotations.TryGetValue(baseTargetExpression, out annotation)) { result = this.RebindMemberAccess(m, annotation); } else { result = Expression.MakeMemberAccess(baseTargetExpression, m.Member); } } return(result); }
#pragma warning restore 649 #endif #endregion Private fields. internal MaterializeAtom(DataServiceContext context, XmlReader reader, QueryComponents queryComponents, ProjectionPlan plan, MergeOption mergeOption) { Debug.Assert(queryComponents != null, "queryComponents != null"); this.context = context; this.elementType = queryComponents.LastSegmentType; this.MergeOptionValue = mergeOption; this.ignoreMissingProperties = context.IgnoreMissingProperties; this.reader = (reader == null) ? null : new System.Data.Services.Client.Xml.XmlAtomErrorReader(reader); this.countValue = CountStateInitial; this.expectingSingleValue = ClientConvert.IsKnownNullableType(elementType); Debug.Assert(reader != null, "Materializer reader is null! Did you mean to use Materializer.ResultsWrapper/EmptyResults?"); reader.Settings.NameTable.Add(context.DataNamespace); string typeScheme = this.context.TypeScheme.OriginalString; this.parser = new AtomParser(this.reader, AtomParser.XElementBuilderCallback, typeScheme, context.DataNamespace); AtomMaterializerLog log = new AtomMaterializerLog(this.context, mergeOption); Type implementationType; Type materializerType = GetTypeForMaterializer(this.expectingSingleValue, this.elementType, out implementationType); this.materializer = new AtomMaterializer(parser, context, materializerType, this.ignoreMissingProperties, mergeOption, log, this.MaterializedObjectCallback, queryComponents, plan); }
internal override Expression VisitMemberAccess(MemberExpression m) { Debug.Assert(m != null, "m != null"); if (ClientConvert.IsKnownNullableType(m.Expression.Type)) { return(base.VisitMemberAccess(m)); } if (!ClientType.CheckElementTypeIsEntity(m.Expression.Type) || IsCollectionProducingExpression(m.Expression)) { throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString())); } PropertyInfo pi = null; if (ResourceBinder.PatternRules.MatchNonPrivateReadableProperty(m, out pi)) { Expression e = base.VisitMemberAccess(m); box.AppendToPath(pi); return(e); } throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString())); }
/// <summary> /// User hook to resolve name into a type. /// </summary> /// <param name="wireName">Name to resolve.</param> /// <param name="expectedType">Expected type for the name.</param> /// <returns>the type as returned by the resolver. If no resolver is registered or resolver returns null, expected type is returned.</returns> /// <exception cref="InvalidOperationException">if ResolveType function returns a type not assignable to the userType</exception> private Type ResolveTypeFromName(string wireName, Type expectedType) { Debug.Assert(!String.IsNullOrEmpty(wireName), "!String.IsNullOrEmpty(wireName)"); Debug.Assert(expectedType != null, "userType != null"); // If there is a mismatch between the wireName and expected type (For e.g. wireName is Edm.Int32 and expectedType is a complex type) // we will return Edm.Int32 from this method and ODatalib fails stating the type kind do not match. Type payloadType; if (!ClientConvert.ToNamedType(wireName, out payloadType)) { payloadType = this.resolveTypeFromName(wireName); if (payloadType == null) { // if the type resolution method returns null or the ResolveType property was not set #if !ASTORIA_LIGHT && !PORTABLELIB payloadType = ClientTypeCache.ResolveFromName(wireName, expectedType); #else payloadType = ClientTypeCache.ResolveFromName(wireName, expectedType, this.GetType()); #endif } if (!this.skipTypeAssignabilityCheck && (payloadType != null) && (!expectedType.IsAssignableFrom(payloadType))) { // throw an exception if the type from the resolver is not assignable to the expected type throw Error.InvalidOperation(Strings.Deserialize_Current(expectedType, payloadType)); } } return(payloadType ?? expectedType); }
/// <summary>Create a request for a specific Uri</summary> /// <param name="requestUri">The URI for the request.</param> public DataServiceRequest(Uri requestUri) { Util.CheckArgumentNull(requestUri, "requestUri"); Type elementType = typeof(TElement); elementType = ClientConvert.IsKnownType(elementType) ? elementType : TypeSystem.GetElementType(elementType); this.queryComponents = new QueryComponents(requestUri, Util.DataServiceVersionEmpty, elementType, null, null); }
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); }
internal override Expression VisitConstant(ConstantExpression c) { string result = null; if (c.Value == null) { this.builder.Append(UriHelper.NULL); return(c); } else if (!ClientConvert.TryKeyPrimitiveToString(c.Value, out result)) { throw new InvalidOperationException(Strings.ALinq_CouldNotConvert(c.Value)); } Debug.Assert(result != null, "result != null"); this.builder.Append(System.Uri.EscapeDataString(result)); return(c); }
private Type ResolveTypeFromName(string wireName, Type expectedType) { Type type; if (!ClientConvert.ToNamedType(wireName, out type)) { type = this.ResponseInfo.ResolveTypeFromName(wireName); if (type == null) { type = ClientTypeCache.ResolveFromName(wireName, expectedType); } if ((!this.projectionQuery && (type != null)) && !expectedType.IsAssignableFrom(type)) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_Current(expectedType, type)); } } return(type ?? expectedType); }
private string TypeNameForUri(Type type) { Debug.Assert(type != null, "type != null"); type = Nullable.GetUnderlyingType(type) ?? type; if (ClientConvert.IsKnownType(type)) { if (ClientConvert.IsSupportedPrimitiveTypeForUri(type)) { return(ClientConvert.ToTypeName(type)); } throw new NotSupportedException(Strings.ALinq_CantCastToUnsupportedPrimitive(type.Name)); } else { return(this.context.ResolveNameFromType(type) ?? type.FullName); } }
internal override Expression VisitConstant(ConstantExpression c) { string result = null; if (c.Value == null) { this.builder.Append("null"); return(c); } if (!ClientConvert.TryKeyPrimitiveToString(c.Value, out result)) { if (!this.cantTranslateExpression) { throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_CouldNotConvert(c.Value)); } return(c); } this.builder.Append(result); return(c); }
internal override Expression VisitUnary(UnaryExpression u) { UnaryExpression visited = (UnaryExpression)base.VisitUnary(u); Expression result = visited; this.RecordRewrite(u, result); if ((visited.NodeType == ExpressionType.Convert || visited.NodeType == ExpressionType.TypeAs) && visited.Type.IsAssignableFrom(visited.Operand.Type)) { if (!ClientConvert.IsKnownNullableType(visited.Operand.Type) && !ClientConvert.IsKnownNullableType(visited.Type) || visited.Operand.Type == visited.Type) { if (!(ClientType.CheckElementTypeIsEntity(visited.Operand.Type) && ProjectionAnalyzer.IsCollectionProducingExpression(visited.Operand))) { result = visited.Operand; } } } return(result); }
internal override Expression VisitUnary(UnaryExpression u) { Debug.Assert(u != null, "u != null"); if (ResourceBinder.PatternRules.MatchConvertToAssignable(u)) { return(base.VisitUnary(u)); } if ((u.NodeType == ExpressionType.Convert) || (u.NodeType == ExpressionType.ConvertChecked)) { Type sourceType = Nullable.GetUnderlyingType(u.Operand.Type) ?? u.Operand.Type; Type targetType = Nullable.GetUnderlyingType(u.Type) ?? u.Type; if (ClientConvert.IsKnownType(sourceType) && ClientConvert.IsKnownType(targetType)) { return(base.Visit(u.Operand)); } } throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, u.ToString())); }
internal override object Materialize(Type clrType) { return(ClientConvert.ChangeType(this.Text, clrType)); }
/// <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); }
/// <summary> /// Override of the base Visitor method, which actually performs mapping search and serialization /// </summary> /// <param name="targetSegment">Current segment being checked for mapping</param> /// <param name="kind">Which sub segments to serialize</param> protected override void Serialize(EpmTargetPathSegment targetSegment, EpmSerializationKind kind) { if (targetSegment.HasContent) { EntityPropertyMappingInfo epmInfo = targetSegment.EpmInfo; Object propertyValue; try { propertyValue = epmInfo.ReadPropertyValue(this.Element); } catch (System.Reflection.TargetInvocationException) { throw; } String contentType; Action <String> contentWriter; switch (epmInfo.Attribute.TargetTextContentKind) { case SyndicationTextContentKind.Html: contentType = "html"; contentWriter = this.Target.WriteString; break; case SyndicationTextContentKind.Xhtml: contentType = "xhtml"; contentWriter = this.Target.WriteRaw; break; default: contentType = "text"; contentWriter = this.Target.WriteString; break; } Action <String, bool, bool> textSyndicationWriter = (c, nonTextPossible, atomDateConstruct) => { this.Target.WriteStartElement(c, XmlConstants.AtomNamespace); if (nonTextPossible) { this.Target.WriteAttributeString(XmlConstants.AtomTypeAttributeName, String.Empty, contentType); } // As per atomPub spec dateConstructs must contain valid datetime. Therefore we need to fill atom:updated/atom:published // field with something (e.g. DateTimeOffset.MinValue) if the user wants to map null to either of these fields. This will // satisfy protocol requirements and Syndication API. Note that the content will still contain information saying that the // mapped property is supposed to be null - therefore the server will know that the actual value sent by the user is null. // For all other elements we can use empty string since the content is not validated. String textPropertyValue = propertyValue != null?ClientConvert.ToString(propertyValue, atomDateConstruct) : atomDateConstruct?ClientConvert.ToString(DateTime.MinValue, atomDateConstruct) : String.Empty; contentWriter(textPropertyValue); this.Target.WriteEndElement(); }; switch (epmInfo.Attribute.TargetSyndicationItem) { case SyndicationItemProperty.AuthorEmail: case SyndicationItemProperty.ContributorEmail: textSyndicationWriter(XmlConstants.AtomEmailElementName, false, false); break; case SyndicationItemProperty.AuthorName: case SyndicationItemProperty.ContributorName: textSyndicationWriter(XmlConstants.AtomNameElementName, false, false); this.authorNamePresent = true; break; case SyndicationItemProperty.AuthorUri: case SyndicationItemProperty.ContributorUri: textSyndicationWriter(XmlConstants.AtomUriElementName, false, false); break; case SyndicationItemProperty.Updated: textSyndicationWriter(XmlConstants.AtomUpdatedElementName, false, true); this.updatedPresent = true; break; case SyndicationItemProperty.Published: textSyndicationWriter(XmlConstants.AtomPublishedElementName, false, true); break; case SyndicationItemProperty.Rights: textSyndicationWriter(XmlConstants.AtomRightsElementName, true, false); break; case SyndicationItemProperty.Summary: textSyndicationWriter(XmlConstants.AtomSummaryElementName, true, false); break; case SyndicationItemProperty.Title: textSyndicationWriter(XmlConstants.AtomTitleElementName, true, false); break; default: Debug.Assert(false, "Unhandled SyndicationItemProperty enum value - should never get here."); break; } } else { if (targetSegment.SegmentName == XmlConstants.AtomAuthorElementName) { this.CreateAuthor(false); base.Serialize(targetSegment, kind); this.FinishAuthor(); } else if (targetSegment.SegmentName == XmlConstants.AtomContributorElementName) { this.Target.WriteStartElement(XmlConstants.AtomContributorElementName, XmlConstants.AtomNamespace); base.Serialize(targetSegment, kind); this.Target.WriteEndElement(); } else { Debug.Assert(false, "Only authors and contributors have nested elements"); } } }
private MaterializeAtom ReadPropertyFromRawData(ClientPropertyAnnotation property) { MaterializeAtom atom; DataServiceContext source = (DataServiceContext)base.Source; bool applyingChanges = source.ApplyingChanges; try { source.ApplyingChanges = true; string mime = null; Encoding encoding = null; Type type = property.EntityCollectionItemType ?? property.NullablePropertyType; IList results = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(new Type[] { type })); HttpProcessUtility.ReadContentType(base.ContentType, out mime, out encoding); using (Stream stream = base.GetResponseStream()) { if (property.PropertyType == typeof(byte[])) { int contentLength = (int)base.ContentLength; byte[] buffer = null; if (contentLength >= 0) { buffer = ReadByteArrayWithContentLength(stream, contentLength); } else { buffer = ReadByteArrayChunked(stream); } results.Add(buffer); property.SetValue(this.entity, buffer, this.propertyName, false); } else { StreamReader reader = new StreamReader(stream, encoding); object obj2 = (property.PropertyType == typeof(string)) ? reader.ReadToEnd() : ClientConvert.ChangeType(reader.ReadToEnd(), property.PropertyType); results.Add(obj2); property.SetValue(this.entity, obj2, this.propertyName, false); } } if (property.MimeTypeProperty != null) { property.MimeTypeProperty.SetValue(this.entity, mime, null, false); } atom = MaterializeAtom.CreateWrapper(source, results); } finally { source.ApplyingChanges = applyingChanges; } return(atom); }
protected override void Serialize(EpmTargetPathSegment targetSegment, EpmSerializationKind kind) { if (targetSegment.HasContent) { EntityPropertyMappingInfo epmInfo = targetSegment.EpmInfo; Object propertyValue; try { propertyValue = epmInfo.PropValReader.DynamicInvoke(this.Element); } catch (System.Reflection.TargetInvocationException) { throw; } String contentType; Action <String> contentWriter; switch (epmInfo.Attribute.TargetTextContentKind) { case SyndicationTextContentKind.Html: contentType = "html"; contentWriter = this.Target.WriteString; break; case SyndicationTextContentKind.Xhtml: contentType = "xhtml"; contentWriter = this.Target.WriteRaw; break; default: contentType = "text"; contentWriter = this.Target.WriteString; break; } Action <String, bool, bool> textSyndicationWriter = (c, nonTextPossible, atomDateConstruct) => { this.Target.WriteStartElement(c, XmlConstants.AtomNamespace); if (nonTextPossible) { this.Target.WriteAttributeString(XmlConstants.AtomTypeAttributeName, String.Empty, contentType); } String textPropertyValue = propertyValue != null?ClientConvert.ToString(propertyValue, atomDateConstruct) : atomDateConstruct?ClientConvert.ToString(DateTime.MinValue, atomDateConstruct) : String.Empty; contentWriter(textPropertyValue); this.Target.WriteEndElement(); }; switch (epmInfo.Attribute.TargetSyndicationItem) { case SyndicationItemProperty.AuthorEmail: case SyndicationItemProperty.ContributorEmail: textSyndicationWriter(XmlConstants.AtomEmailElementName, false, false); break; case SyndicationItemProperty.AuthorName: case SyndicationItemProperty.ContributorName: textSyndicationWriter(XmlConstants.AtomNameElementName, false, false); this.authorNamePresent = true; break; case SyndicationItemProperty.AuthorUri: case SyndicationItemProperty.ContributorUri: textSyndicationWriter(XmlConstants.AtomUriElementName, false, false); break; case SyndicationItemProperty.Updated: textSyndicationWriter(XmlConstants.AtomUpdatedElementName, false, true); this.updatedPresent = true; break; case SyndicationItemProperty.Published: textSyndicationWriter(XmlConstants.AtomPublishedElementName, false, true); break; case SyndicationItemProperty.Rights: textSyndicationWriter(XmlConstants.AtomRightsElementName, true, false); break; case SyndicationItemProperty.Summary: textSyndicationWriter(XmlConstants.AtomSummaryElementName, true, false); break; case SyndicationItemProperty.Title: textSyndicationWriter(XmlConstants.AtomTitleElementName, true, false); break; default: Debug.Assert(false, "Unhandled SyndicationItemProperty enum value - should never get here."); break; } } else { if (targetSegment.SegmentName == XmlConstants.AtomAuthorElementName) { this.CreateAuthor(false); base.Serialize(targetSegment, kind); this.FinishAuthor(); } else if (targetSegment.SegmentName == XmlConstants.AtomContributorElementName) { this.Target.WriteStartElement(XmlConstants.AtomContributorElementName, XmlConstants.AtomNamespace); base.Serialize(targetSegment, kind); this.Target.WriteEndElement(); } else { Debug.Assert(false, "Only authors and contributors have nested elements"); } } }
public T Field <T>(string property) { return((T)ClientConvert.VerifyCast(typeof(T), this[property])); }
/// <summary> /// discover and prepare properties for usage /// </summary> /// <param name="type">type being processed</param> /// <param name="typeName">parameter name</param> /// <param name="skipSettableCheck">Whether the skip the check for settable properties.</param> private ClientType(Type type, string typeName, bool skipSettableCheck) { Debug.Assert(null != type, "null type"); Debug.Assert(!String.IsNullOrEmpty(typeName), "empty typeName"); this.ElementTypeName = typeName; this.ElementType = Nullable.GetUnderlyingType(type) ?? type; #if ASTORIA_OPEN_OBJECT string openObjectPropertyName = null; #endif if (!ClientConvert.IsKnownType(this.ElementType)) { #if ASTORIA_OPEN_OBJECT #region OpenObject determined by walking type hierarchy and looking for [OpenObjectAttribute("PropertyName")] Type openObjectDeclared = this.ElementType; for (Type tmp = openObjectDeclared; (null != tmp) && (typeof(object) != tmp); tmp = tmp.BaseType) { object[] attributes = openObjectDeclared.GetCustomAttributes(typeof(OpenObjectAttribute), false); if (1 == attributes.Length) { if (null != openObjectPropertyName) { throw Error.InvalidOperation(Strings.Clienttype_MultipleOpenProperty(this.ElementTypeName)); } openObjectPropertyName = ((OpenObjectAttribute)attributes[0]).OpenObjectPropertyName; openObjectDeclared = tmp; } } #endregion #endif Type keyPropertyDeclaredType = null; bool isEntity = type.GetCustomAttributes(true).OfType <DataServiceEntityAttribute>().Any(); DataServiceKeyAttribute dska = type.GetCustomAttributes(true).OfType <DataServiceKeyAttribute>().FirstOrDefault(); foreach (PropertyInfo pinfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { //// examples where class<PropertyType> //// the normal examples //// PropertyType Property { get; set } //// Nullable<PropertyType> Property { get; set; } //// if 'Property: struct' then we would be unable set the property during construction (and have them stick) //// but when its a class, we can navigate if non-null and set the nested properties //// PropertyType Property { get; } where PropertyType: class //// we do support adding elements to collections //// ICollection<PropertyType> { get; /*ignored set;*/ } //// indexed properties are not suported because //// we don't have anything to use as the index //// PropertyType Property[object x] { /*ignored get;*/ /*ignored set;*/ } //// also ignored //// if PropertyType.IsPointer (like byte*) //// if PropertyType.IsArray except for byte[] and char[] //// if PropertyType == IntPtr or UIntPtr Type ptype = pinfo.PropertyType; // class / interface / value ptype = Nullable.GetUnderlyingType(ptype) ?? ptype; if (ptype.IsPointer || (ptype.IsArray && (typeof(byte[]) != ptype) && typeof(char[]) != ptype) || (typeof(IntPtr) == ptype) || (typeof(UIntPtr) == ptype)) { continue; } Debug.Assert(!ptype.ContainsGenericParameters, "remove when test case is found that encounters this"); if (pinfo.CanRead && (!ptype.IsValueType || pinfo.CanWrite) && !ptype.ContainsGenericParameters && (0 == pinfo.GetIndexParameters().Length)) { #region IsKey? bool keyProperty = dska != null?dska.KeyNames.Contains(pinfo.Name) : false; if (keyProperty) { if (null == keyPropertyDeclaredType) { keyPropertyDeclaredType = pinfo.DeclaringType; } else if (keyPropertyDeclaredType != pinfo.DeclaringType) { throw Error.InvalidOperation(Strings.ClientType_KeysOnDifferentDeclaredType(this.ElementTypeName)); } if (!ClientConvert.IsKnownType(ptype)) { throw Error.InvalidOperation(Strings.ClientType_KeysMustBeSimpleTypes(this.ElementTypeName)); } this.KeyCount++; } #endregion #if ASTORIA_OPEN_OBJECT #region IsOpenObjectProperty? bool openProperty = (openObjectPropertyName == pinfo.Name) && typeof(IDictionary <string, object>).IsAssignableFrom(ptype); Debug.Assert(keyProperty != openProperty || (!keyProperty && !openProperty), "key can't be open type"); #endregion ClientProperty property = new ClientProperty(pinfo, ptype, keyProperty, openProperty); if (!property.OpenObjectProperty) #else ClientProperty property = new ClientProperty(pinfo, ptype, keyProperty); #endif { if (!this.properties.Add(property, ClientProperty.NameEquality)) { // 2nd property with same name shadows another property int shadow = this.IndexOfProperty(property.PropertyName); if (!property.DeclaringType.IsAssignableFrom(this.properties[shadow].DeclaringType)) { // the new property is on the most derived class this.properties.RemoveAt(shadow); this.properties.Add(property, null); } } } #if ASTORIA_OPEN_OBJECT else { if (pinfo.DeclaringType == openObjectDeclared) { this.openProperties = property; } } #endif } } #region No KeyAttribute, discover key by name pattern { DeclaringType.Name+ID, ID } if (null == keyPropertyDeclaredType) { ClientProperty key = null; for (int i = this.properties.Count - 1; 0 <= i; --i) { string propertyName = this.properties[i].PropertyName; if (propertyName.EndsWith("ID", StringComparison.Ordinal)) { string declaringTypeName = this.properties[i].DeclaringType.Name; if ((propertyName.Length == (declaringTypeName.Length + 2)) && propertyName.StartsWith(declaringTypeName, StringComparison.Ordinal)) { // matched "DeclaringType.Name+ID" pattern if ((null == keyPropertyDeclaredType) || this.properties[i].DeclaringType.IsAssignableFrom(keyPropertyDeclaredType)) { keyPropertyDeclaredType = this.properties[i].DeclaringType; key = this.properties[i]; } } else if ((null == keyPropertyDeclaredType) && (2 == propertyName.Length)) { // matched "ID" pattern keyPropertyDeclaredType = this.properties[i].DeclaringType; key = this.properties[i]; } } } if (null != key) { Debug.Assert(0 == this.KeyCount, "shouldn't have a key yet"); key.KeyProperty = true; this.KeyCount++; } } else if (this.KeyCount != dska.KeyNames.Count) { var m = (from string a in dska.KeyNames where null == (from b in this.properties where b.PropertyName == a select b).FirstOrDefault() select a).First <string>(); throw Error.InvalidOperation(Strings.ClientType_MissingProperty(this.ElementTypeName, m)); } #endregion this.IsEntityType = (null != keyPropertyDeclaredType) || isEntity; Debug.Assert(this.KeyCount == this.Properties.Where(k => k.KeyProperty).Count(), "KeyCount mismatch"); this.WireUpMimeTypeProperties(); this.CheckMediaLinkEntry(); if (!skipSettableCheck) { #if ASTORIA_OPEN_OBJECT if ((0 == this.properties.Count) && (null == this.openProperties)) #else if (0 == this.properties.Count) #endif { // implicit construction? throw Error.InvalidOperation(Strings.ClientType_NoSettableFields(this.ElementTypeName)); } } }
private ODataRequestMessageWrapper CheckAndProcessMediaEntryPost(EntityDescriptor entityDescriptor) { ClientEdmModel model = ClientEdmModel.GetModel(base.RequestInfo.MaxProtocolVersion); ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); if (!clientTypeAnnotation.IsMediaLinkEntry && !entityDescriptor.IsMediaLinkEntry) { return(null); } if ((clientTypeAnnotation.MediaDataMember == null) && (entityDescriptor.SaveStream == null)) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Context_MLEWithoutSaveStream(clientTypeAnnotation.ElementTypeName)); } ODataRequestMessageWrapper mediaResourceRequest = null; if (clientTypeAnnotation.MediaDataMember != null) { string contentType = null; int length = 0; if (clientTypeAnnotation.MediaDataMember.MimeTypeProperty == null) { contentType = "application/octet-stream"; } else { object obj2 = clientTypeAnnotation.MediaDataMember.MimeTypeProperty.GetValue(entityDescriptor.Entity); string str2 = (obj2 != null) ? obj2.ToString() : null; if (string.IsNullOrEmpty(str2)) { throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Context_NoContentTypeForMediaLink(clientTypeAnnotation.ElementTypeName, clientTypeAnnotation.MediaDataMember.MimeTypeProperty.PropertyName)); } contentType = str2; } object propertyValue = clientTypeAnnotation.MediaDataMember.GetValue(entityDescriptor.Entity); if (propertyValue == null) { base.mediaResourceRequestStream = null; } else { byte[] bytes = propertyValue as byte[]; if (bytes == null) { string str3; Encoding encoding; HttpProcessUtility.ReadContentType(contentType, out str3, out encoding); if (encoding == null) { encoding = Encoding.UTF8; contentType = contentType + ";charset=UTF-8"; } bytes = encoding.GetBytes(ClientConvert.ToString(propertyValue)); } length = bytes.Length; base.mediaResourceRequestStream = new MemoryStream(bytes, 0, bytes.Length, false, true); } mediaResourceRequest = this.CreateMediaResourceRequest(entityDescriptor.GetResourceUri(base.RequestInfo.BaseUriResolver, false), "POST", Util.DataServiceVersion1, clientTypeAnnotation.MediaDataMember == null, true); mediaResourceRequest.SetHeader("Content-Length", length.ToString(CultureInfo.InvariantCulture)); mediaResourceRequest.SetHeader("Content-Type", contentType); mediaResourceRequest.AddHeadersToReset("Content-Length"); mediaResourceRequest.AddHeadersToReset("Content-Type"); } else { mediaResourceRequest = this.CreateMediaResourceRequest(entityDescriptor.GetResourceUri(base.RequestInfo.BaseUriResolver, false), "POST", Util.DataServiceVersion1, clientTypeAnnotation.MediaDataMember == null, true); this.SetupMediaResourceRequest(mediaResourceRequest, entityDescriptor.SaveStream, null); } entityDescriptor.State = EntityStates.Modified; return(mediaResourceRequest); }
private MaterializeAtom ReadPropertyFromRawData(ClientPropertyAnnotation property) { DataServiceContext context = (DataServiceContext)this.Source; bool merging = context.ApplyingChanges; try { context.ApplyingChanges = true; // if this is the data property for a media entry, what comes back // is the raw value (no markup) #if ASTORIA_OPEN_OBJECT object openProps = null; #endif string mimeType = null; Encoding encoding = null; Type elementType = property.EntityCollectionItemType ?? property.NullablePropertyType; IList results = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(elementType)); ContentTypeUtil.ReadContentType(this.ContentType, out mimeType, out encoding); using (Stream responseStream = this.GetResponseStream()) { // special case byte[], and for everything else let std conversion kick-in if (property.PropertyType == typeof(byte[])) { int total = checked ((int)this.ContentLength); byte[] buffer = null; if (total >= 0) { buffer = LoadPropertyResult.ReadByteArrayWithContentLength(responseStream, total); } else { buffer = LoadPropertyResult.ReadByteArrayChunked(responseStream); } results.Add(buffer); #if ASTORIA_OPEN_OBJECT property.SetValue(this.entity, buffer, this.propertyName, ref openProps, false); #else property.SetValue(this.entity, buffer, this.propertyName, false); #endif } else { // responseStream will disposed, StreamReader doesn't need to dispose of it. StreamReader reader = new StreamReader(responseStream, encoding); object convertedValue = property.PropertyType == typeof(string) ? reader.ReadToEnd() : ClientConvert.ChangeType(reader.ReadToEnd(), property.PropertyType); results.Add(convertedValue); #if ASTORIA_OPEN_OBJECT property.SetValue(this.entity, convertedValue, this.propertyName, ref openProps, false); #else property.SetValue(this.entity, convertedValue, this.propertyName, false); #endif } } #if ASTORIA_OPEN_OBJECT Debug.Assert(openProps == null, "These should not be set in this path"); #endif if (property.MimeTypeProperty != null) { // an implication of this 3rd-arg-null is that mime type properties cannot be open props #if ASTORIA_OPEN_OBJECT property.MimeTypeProperty.SetValue(this.entity, mimeType, null, ref openProps, false); Debug.Assert(openProps == null, "These should not be set in this path"); #else property.MimeTypeProperty.SetValue(this.entity, mimeType, null, false); #endif } return(MaterializeAtom.CreateWrapper(context, results)); } finally { context.ApplyingChanges = merging; } }
private ClientType(Type type, string typeName, bool skipSettableCheck) { Debug.Assert(null != type, "null type"); Debug.Assert(!String.IsNullOrEmpty(typeName), "empty typeName"); this.ElementTypeName = typeName; this.ElementType = Nullable.GetUnderlyingType(type) ?? type; #if ASTORIA_OPEN_OBJECT string openObjectPropertyName = null; #endif if (!ClientConvert.IsKnownType(this.ElementType)) { #if ASTORIA_OPEN_OBJECT #region OpenObject determined by walking type hierarchy and looking for [OpenObjectAttribute("PropertyName")] Type openObjectDeclared = this.ElementType; for (Type tmp = openObjectDeclared; (null != tmp) && (typeof(object) != tmp); tmp = tmp.BaseType) { object[] attributes = openObjectDeclared.GetCustomAttributes(typeof(OpenObjectAttribute), false); if (1 == attributes.Length) { if (null != openObjectPropertyName) { throw Error.InvalidOperation(Strings.Clienttype_MultipleOpenProperty(this.ElementTypeName)); } openObjectPropertyName = ((OpenObjectAttribute)attributes[0]).OpenObjectPropertyName; openObjectDeclared = tmp; } } #endregion #endif Type keyPropertyDeclaredType = null; bool isEntity = type.GetCustomAttributes(true).OfType <DataServiceEntityAttribute>().Any(); DataServiceKeyAttribute dska = type.GetCustomAttributes(true).OfType <DataServiceKeyAttribute>().FirstOrDefault(); foreach (PropertyInfo pinfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { Type ptype = pinfo.PropertyType; ptype = Nullable.GetUnderlyingType(ptype) ?? ptype; if (ptype.IsPointer || (ptype.IsArray && (typeof(byte[]) != ptype) && typeof(char[]) != ptype) || (typeof(IntPtr) == ptype) || (typeof(UIntPtr) == ptype)) { continue; } Debug.Assert(!ptype.ContainsGenericParameters, "remove when test case is found that encounters this"); if (pinfo.CanRead && (!ptype.IsValueType || pinfo.CanWrite) && !ptype.ContainsGenericParameters && (0 == pinfo.GetIndexParameters().Length)) { #region IsKey? bool keyProperty = dska != null?dska.KeyNames.Contains(pinfo.Name) : false; if (keyProperty) { if (null == keyPropertyDeclaredType) { keyPropertyDeclaredType = pinfo.DeclaringType; } else if (keyPropertyDeclaredType != pinfo.DeclaringType) { throw Error.InvalidOperation(Strings.ClientType_KeysOnDifferentDeclaredType(this.ElementTypeName)); } if (!ClientConvert.IsKnownType(ptype)) { throw Error.InvalidOperation(Strings.ClientType_KeysMustBeSimpleTypes(this.ElementTypeName)); } this.KeyCount++; } #endregion #if ASTORIA_OPEN_OBJECT #region IsOpenObjectProperty? bool openProperty = (openObjectPropertyName == pinfo.Name) && typeof(IDictionary <string, object>).IsAssignableFrom(ptype); Debug.Assert(keyProperty != openProperty || (!keyProperty && !openProperty), "key can't be open type"); #endregion ClientProperty property = new ClientProperty(pinfo, ptype, keyProperty, openProperty); if (!property.OpenObjectProperty) #else ClientProperty property = new ClientProperty(pinfo, ptype, keyProperty); #endif { if (!this.properties.Add(property, ClientProperty.NameEquality)) { int shadow = this.IndexOfProperty(property.PropertyName); if (!property.DeclaringType.IsAssignableFrom(this.properties[shadow].DeclaringType)) { this.properties.RemoveAt(shadow); this.properties.Add(property, null); } } } #if ASTORIA_OPEN_OBJECT else { if (pinfo.DeclaringType == openObjectDeclared) { this.openProperties = property; } } #endif } } #region No KeyAttribute, discover key by name pattern { DeclaringType.Name+ID, ID } if (null == keyPropertyDeclaredType) { ClientProperty key = null; for (int i = this.properties.Count - 1; 0 <= i; --i) { string propertyName = this.properties[i].PropertyName; if (propertyName.EndsWith("ID", StringComparison.Ordinal)) { string declaringTypeName = this.properties[i].DeclaringType.Name; if ((propertyName.Length == (declaringTypeName.Length + 2)) && propertyName.StartsWith(declaringTypeName, StringComparison.Ordinal)) { if ((null == keyPropertyDeclaredType) || this.properties[i].DeclaringType.IsAssignableFrom(keyPropertyDeclaredType)) { keyPropertyDeclaredType = this.properties[i].DeclaringType; key = this.properties[i]; } } else if ((null == keyPropertyDeclaredType) && (2 == propertyName.Length)) { keyPropertyDeclaredType = this.properties[i].DeclaringType; key = this.properties[i]; } } } if (null != key) { Debug.Assert(0 == this.KeyCount, "shouldn't have a key yet"); key.KeyProperty = true; this.KeyCount++; } } else if (this.KeyCount != dska.KeyNames.Count) { var m = (from string a in dska.KeyNames where null == (from b in this.properties where b.PropertyName == a select b).FirstOrDefault() select a).First <string>(); throw Error.InvalidOperation(Strings.ClientType_MissingProperty(this.ElementTypeName, m)); } #endregion this.IsEntityType = (null != keyPropertyDeclaredType) || isEntity; Debug.Assert(this.KeyCount == this.Properties.Where(k => k.KeyProperty).Count(), "KeyCount mismatch"); this.WireUpMimeTypeProperties(); this.CheckMediaLinkEntry(); if (!skipSettableCheck) { #if ASTORIA_OPEN_OBJECT if ((0 == this.properties.Count) && (null == this.openProperties)) #else if (0 == this.properties.Count) #endif { throw Error.InvalidOperation(Strings.ClientType_NoSettableFields(this.ElementTypeName)); } } }