コード例 #1
0
#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);
        }
コード例 #2
0
            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()));
            }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
#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);
        }
コード例 #6
0
            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()));
            }
コード例 #7
0
ファイル: TypeResolver.cs プロジェクト: tapika/swupd
        /// <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);
        }
コード例 #8
0
        /// <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);
        }
コード例 #9
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);
        }
コード例 #10
0
        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);
        }
コード例 #11
0
ファイル: TypeResolver.cs プロジェクト: modulexcite/pash-1
        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);
        }
コード例 #12
0
        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);
            }
        }
コード例 #13
0
        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);
        }
コード例 #14
0
        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);
        }
コード例 #15
0
            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()));
            }
コード例 #16
0
 internal override object Materialize(Type clrType)
 {
     return(ClientConvert.ChangeType(this.Text, clrType));
 }
コード例 #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
        /// <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");
                }
            }
        }
コード例 #19
0
        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);
        }
コード例 #20
0
        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");
                }
            }
        }
コード例 #21
0
 public T Field <T>(string property)
 {
     return((T)ClientConvert.VerifyCast(typeof(T), this[property]));
 }
コード例 #22
0
ファイル: ClientType.cs プロジェクト: dox0/DotNet471RS3
        /// <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));
                    }
                }
            }
コード例 #23
0
        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);
        }
コード例 #24
0
        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;
            }
        }
コード例 #25
0
ファイル: ClientType.cs プロジェクト: weimingtom/mono-4.3.2
        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)); }
                }
            }