Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Design / system / Data / EntityModel / Emitters / AttributeEmitter.cs / 1305376 / AttributeEmitter.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.CodeDom; using System.Collections.Generic; using System.Data.Metadata.Edm; using System.Data.Services.Common; using System.Data.Services.Design; using System.Diagnostics; using System.Globalization; using System.Linq; namespace System.Data.EntityModel.Emitters { ////// Summary description for AttributeEmitter. /// internal sealed partial class AttributeEmitter { private const string _generatorVersion = "1.0.0"; private const string _generatorName = "System.Data.Services.Design"; private static readonly CodeAttributeDeclaration _generatedCodeAttribute = new CodeAttributeDeclaration( new CodeTypeReference(typeof(System.CodeDom.Compiler.GeneratedCodeAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(_generatorName)), new CodeAttributeArgument(new CodePrimitiveExpression(_generatorVersion))); TypeReference _typeReference; internal TypeReference TypeReference { get { return _typeReference; } } internal AttributeEmitter(TypeReference typeReference) { _typeReference = typeReference; } ////// The method to be called to create the type level attributes for the ItemTypeEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. public void EmitTypeAttributes(EntityTypeEmitter emitter, CodeTypeDeclaration typeDecl) { Debug.Assert(emitter != null, "emitter should not be null"); Debug.Assert(typeDecl != null, "typeDecl should not be null"); if (emitter.Generator.Version != DataServiceCodeVersion.V1) { EmitEpmAttributesForEntityType(emitter.Generator.EdmItemCollection, emitter.Item, typeDecl); EmitStreamAttributesForEntityType(emitter.Item, typeDecl); } object[] keys = emitter.Item.KeyMembers.Select(km => (object) km.Name).ToArray(); typeDecl.CustomAttributes.Add(EmitSimpleAttribute(Utils.WebFrameworkCommonNamespace + "." + "DataServiceKeyAttribute", keys)); } ////// The method to be called to create the type level attributes for the StructuredTypeEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. public void EmitTypeAttributes(StructuredTypeEmitter emitter, CodeTypeDeclaration typeDecl) { Debug.Assert(emitter != null, "emitter should not be null"); Debug.Assert(typeDecl != null, "typeDecl should not be null"); // nothing to do here yet } ////// The method to be called to create the type level attributes for the SchemaTypeEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. public void EmitTypeAttributes(SchemaTypeEmitter emitter, CodeTypeDeclaration typeDecl) { Debug.Assert(emitter != null, "emitter should not be null"); Debug.Assert(typeDecl != null, "typeDecl should not be null"); } ////// The method to be called to create the property level attributes for the PropertyEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. /// Additional attributes to emit public void EmitPropertyAttributes(PropertyEmitter emitter, CodeMemberProperty propertyDecl, ListadditionalAttributes) { if (additionalAttributes != null && additionalAttributes.Count > 0) { try { propertyDecl.CustomAttributes.AddRange(additionalAttributes.ToArray()); } catch (ArgumentNullException e) { emitter.Generator.AddError(Strings.InvalidAttributeSuppliedForProperty(emitter.Item.Name), ModelBuilderErrorCode.InvalidAttributeSuppliedForProperty, EdmSchemaErrorSeverity.Error, e); } } } /// /// The method to be called to create the type level attributes for the NestedTypeEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. public void EmitTypeAttributes(ComplexTypeEmitter emitter, CodeTypeDeclaration typeDecl) { Debug.Assert(emitter != null, "emitter should not be null"); Debug.Assert(typeDecl != null, "typeDecl should not be null"); // not emitting System.Runtime.Serializaton.DataContractAttribute // not emitting System.Serializable } #region Static Methods ////// /// /// /// ///public CodeAttributeDeclaration EmitSimpleAttribute(string attributeType, params object[] arguments) { CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(TypeReference.FromString(attributeType, true)); AddAttributeArguments(attribute, arguments); return attribute; } /// /// /// /// /// public static void AddAttributeArguments(CodeAttributeDeclaration attribute, object[] arguments) { foreach (object argument in arguments) { CodeExpression expression = argument as CodeExpression; if (expression == null) expression = new CodePrimitiveExpression(argument); attribute.Arguments.Add(new CodeAttributeArgument(expression)); } } ////// Adds an XmlIgnore attribute to the given property declaration. This is /// used to explicitly skip certain properties during XML serialization. /// /// the property to mark with XmlIgnore public void AddIgnoreAttributes(CodeMemberProperty propertyDecl) { // not emitting System.Xml.Serialization.XmlIgnoreAttribute // not emitting System.Xml.Serialization.SoapIgnoreAttribute } ////// Adds an Browsable(false) attribute to the given property declaration. /// This is used to explicitly avoid display property in the PropertyGrid. /// /// the property to mark with XmlIgnore public void AddBrowsableAttribute(CodeMemberProperty propertyDecl) { // not emitting System.ComponentModel.BrowsableAttribute } #endregion ////// Add the GeneratedCode attribute to the code type member /// /// the code type member public static void AddGeneratedCodeAttribute(CodeTypeMember ctm) { ctm.CustomAttributes.Add(_generatedCodeAttribute); } ///Given a type detects if it is an open type or not /// Input type ///true if it is an open type, false otherwise private static bool IsOpenType(StructuralType entityType) { MetadataProperty isOpenTypeProperty = entityType.MetadataProperties.FirstOrDefault(x => x.Name == System.Data.Services.XmlConstants.EdmV1dot2Namespace + ":" + System.Data.Services.XmlConstants.DataWebOpenTypeAttributeName); if (isOpenTypeProperty != null) { bool isOpenType; if (!Boolean.TryParse(Convert.ToString(isOpenTypeProperty.Value, CultureInfo.InvariantCulture), out isOpenType)) { throw new InvalidOperationException(Strings.ObjectContext_OpenTypePropertyValueIsNotCorrect(System.Data.Services.XmlConstants.DataWebOpenTypeAttributeName, entityType.Name)); } return isOpenType; } else { return false; } } ////// Checks if the given path corresponds to some open property on the /// Type to check the path for /// Input property path ////// true if there is some open property corresponding to the path, false otherwise bool IsOpenPropertyOnPath(StructuralType baseEntityType, String sourcePath) { Debug.Assert(baseEntityType != null, "Expecting non-null entity type"); if (String.IsNullOrEmpty(sourcePath)) { return false; } String[] propertyPath = sourcePath.Split('/'); EdmMember entityProperty = baseEntityType.Members.SingleOrDefault(p => p.Name == propertyPath[0]); if (entityProperty == null) { if (baseEntityType.BaseType != null) { return IsOpenPropertyOnPath(baseEntityType.BaseType as StructuralType, sourcePath); } else { return IsOpenType(baseEntityType); } } else { StructuralType entityPropertyType = entityProperty.TypeUsage.EdmType as StructuralType; if (entityPropertyType != null) { return IsOpenPropertyOnPath(entityPropertyType, String.Join("/", propertyPath, 1, propertyPath.Length - 1)); } else { return false; } } } ////// Obtains the entity property corresponding to a given sourcePath /// /// Entity type in which to look for property /// Source Path ///EdmMember object corresponding to the property given through source path private static EdmMember GetEntityPropertyFromEpmPath(StructuralType baseEntityType, String sourcePath) { Debug.Assert(baseEntityType != null, "Expecting non-null entity type"); String[] propertyPath = sourcePath.Split('/'); if (!baseEntityType.Members.Any(p => p.Name == propertyPath[0])) { return baseEntityType.BaseType != null ? GetEntityPropertyFromEpmPath(baseEntityType.BaseType as StructuralType, sourcePath) : null; } else { EdmMember entityProperty = null; foreach (var pathSegment in propertyPath) { if (baseEntityType == null) { return null; } entityProperty = baseEntityType.Members.SingleOrDefault(p => p.Name == pathSegment); if (entityProperty == null) { return null; } baseEntityType = entityProperty.TypeUsage.EdmType as StructuralType; } return entityProperty; } } ////// Returns a sequence of attributes corresponding to a complex type with recursion /// /// Complex typed property /// Source path /// Target path /// Namespace prefix /// Namespace Uri /// KeepInContent setting ///Sequence of entity property mapping information for complex type properties private static IEnumerableGetEpmAttrsFromComplexProperty( EdmMember complexProperty, String epmSourcePath, String epmTargetPath, String epmNsPrefix, String epmNsUri, bool epmKeepContent) { Debug.Assert(complexProperty != null, "Expecting non-null complex property"); ComplexType complexType = complexProperty.TypeUsage.EdmType as ComplexType; if (complexType == null) { throw new ArgumentException(Strings.ExpectingComplexTypeForMember(complexProperty.Name, complexProperty.DeclaringType.Name)); } foreach (EdmMember subProperty in complexType.Properties) { String sourcePath = epmSourcePath + "/" + subProperty.Name; String targetPath = epmTargetPath + "/" + subProperty.Name; if (subProperty.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType) { foreach (EntityPropertyMappingAttribute epmAttr in GetEpmAttrsFromComplexProperty(subProperty, sourcePath, targetPath, epmNsPrefix, epmNsUri, epmKeepContent)) { yield return epmAttr; } } else { yield return new EntityPropertyMappingAttribute( sourcePath, targetPath, epmNsPrefix, epmNsUri, epmKeepContent); } } } /// /// Given a resource type, builds the EntityPropertyMappingInfo for each EntityPropertyMappingAttribute on it /// /// EFx metadata item collection that has been loaded /// Entity type for which EntityPropertyMappingAttribute discovery is happening /// Type declaration to add the attributes to private void EmitEpmAttributesForEntityType(EdmItemCollection itemCollection, EntityType entityType, CodeTypeDeclaration typeDecl) { // Get epm information provided at the entity type declaration level IEnumerableextendedProperties = entityType.MetadataProperties.Where(mp => mp.PropertyKind == PropertyKind.Extended); foreach (EpmPropertyInformation propertyInformation in GetEpmPropertyInformation(extendedProperties, entityType.Name, null)) { EdmMember redefinedProperty = GetEntityPropertyFromEpmPath(entityType, propertyInformation.SourcePath); if (redefinedProperty == null) { if (IsOpenPropertyOnPath(entityType, propertyInformation.SourcePath)) { EmitEpmAttributeForEntityProperty( propertyInformation, new EdmInfo { IsComplex = false, Member = null }, typeDecl); } else { throw new InvalidOperationException(Strings.ObjectContext_UnknownPropertyNameInEpmAttributesType(propertyInformation.SourcePath, entityType.Name)); } } else { EmitEpmAttributeForEntityProperty( propertyInformation, new EdmInfo { IsComplex = redefinedProperty.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, Member = redefinedProperty }, typeDecl); } } // Get epm information provided at the entity type property level foreach (EdmMember member in entityType.Members.Where(m => m.DeclaringType == entityType)) { EdmMember entityProperty = entityType.Properties.SingleOrDefault(p => p.DeclaringType == entityType && p.Name == member.Name); IEnumerable extendedMemberProperties = member.MetadataProperties.Where(mdp => mdp.PropertyKind == PropertyKind.Extended); foreach (EpmPropertyInformation propertyInformation in GetEpmPropertyInformation(extendedMemberProperties, entityType.Name, member.Name)) { EdmMember entityPropertyCurrent = entityProperty; if (entityProperty.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType && propertyInformation.PathGiven) { String originalPath = propertyInformation.SourcePath; propertyInformation.SourcePath = entityProperty.Name + "/" + propertyInformation.SourcePath; entityPropertyCurrent = GetEntityPropertyFromEpmPath(entityType, propertyInformation.SourcePath); if (entityPropertyCurrent == null) { if (IsOpenPropertyOnPath(entityProperty.TypeUsage.EdmType as StructuralType, originalPath)) { EmitEpmAttributeForEntityProperty( propertyInformation, new EdmInfo { IsComplex = false, Member = null }, typeDecl); continue; } else { throw new InvalidOperationException(Strings.ObjectContext_UnknownPropertyNameInEpmAttributesMember(originalPath, member.Name, entityType.Name)); } } } EmitEpmAttributeForEntityProperty( propertyInformation, new EdmInfo { IsComplex = entityPropertyCurrent.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, Member = entityPropertyCurrent }, typeDecl); } } } /// /// Given a resource type and its resource proeperty builds the EntityPropertyMappingInfo for the EntityPropertyMappingAttribute on it /// /// EPM information for current property /// Property for which to get the information /// Type declaration to add the attributes to private void EmitEpmAttributeForEntityProperty( EpmPropertyInformation propertyInformation, EdmInfo entityProperty, CodeTypeDeclaration typeDecl) { if (propertyInformation.IsAtom) { if (entityProperty.IsComplex) { throw new InvalidOperationException(Strings.ObjectContext_SyndicationMappingForComplexPropertiesNotAllowed); } else { EntityPropertyMappingAttribute epmAttr = new EntityPropertyMappingAttribute( propertyInformation.SourcePath, propertyInformation.SyndicationItem, propertyInformation.ContentKind, propertyInformation.KeepInContent); this.AddEpmAttributeToTypeDeclaration(epmAttr, typeDecl); } } else { if (entityProperty.IsComplex) { foreach (EntityPropertyMappingAttribute epmAttr in GetEpmAttrsFromComplexProperty( entityProperty.Member, propertyInformation.SourcePath, propertyInformation.TargetPath, propertyInformation.NsPrefix, propertyInformation.NsUri, propertyInformation.KeepInContent)) { this.AddEpmAttributeToTypeDeclaration(epmAttr, typeDecl); } } else { EntityPropertyMappingAttribute epmAttr = new EntityPropertyMappingAttribute( propertyInformation.SourcePath, propertyInformation.TargetPath, propertyInformation.NsPrefix, propertyInformation.NsUri, propertyInformation.KeepInContent); this.AddEpmAttributeToTypeDeclaration(epmAttr, typeDecl); } } } ///Creates an EntityPropertyMappingAttribute and adds it to the /// Attribute to add /// Type declaration for which the attribute is generated private void AddEpmAttributeToTypeDeclaration(EntityPropertyMappingAttribute epmAttr, CodeTypeDeclaration typeDecl) { if (epmAttr.TargetSyndicationItem != SyndicationItemProperty.CustomProperty) { var syndicationItem = new CodeFieldReferenceExpression( new CodeTypeReferenceExpression(typeof(SyndicationItemProperty)), epmAttr.TargetSyndicationItem.ToString()); var contentKind = new CodeFieldReferenceExpression( new CodeTypeReferenceExpression(typeof(SyndicationTextContentKind)), epmAttr.TargetTextContentKind.ToString()); CodeAttributeDeclaration attribute = new CodeAttributeDeclaration( TypeReference.FromString( Utils.WebFrameworkCommonNamespace + "." + "EntityPropertyMappingAttribute", true)); AddAttributeArguments(attribute, new object[] { epmAttr.SourcePath, syndicationItem, contentKind, epmAttr.KeepInContent }); typeDecl.CustomAttributes.Add(attribute); } else { CodeAttributeDeclaration attribute = new CodeAttributeDeclaration( TypeReference.FromString( Utils.WebFrameworkCommonNamespace + "." + "EntityPropertyMappingAttribute", true)); AddAttributeArguments(attribute, new object[] { epmAttr.SourcePath, epmAttr.TargetPath, epmAttr.TargetNamespacePrefix, epmAttr.TargetNamespaceUri, epmAttr.KeepInContent }); typeDecl.CustomAttributes.Add(attribute); } } ////// Given a resource type, generates the HasStreamAttribute for it /// /// Entity type for which HasStreamAttribute discovery is happening /// Type declaration to add the attributes to private void EmitStreamAttributesForEntityType(EntityType entityType, CodeTypeDeclaration typeDecl) { IEnumerablehasStreamMetadataProperties = entityType.MetadataProperties.Where(mp => mp.PropertyKind == PropertyKind.Extended && mp.Name == System.Data.Services.XmlConstants.DataWebMetadataNamespace + ":" + System.Data.Services.XmlConstants.DataWebAccessHasStreamAttribute); MetadataProperty hasStreamMetadataProperty = null; foreach (MetadataProperty p in hasStreamMetadataProperties) { if (hasStreamMetadataProperty != null) { throw new InvalidOperationException( Strings.ObjectContext_MultipleValuesForSameExtendedAttributeType( System.Data.Services.XmlConstants.DataWebAccessHasStreamAttribute, entityType.Name)); } hasStreamMetadataProperty = p; } if (hasStreamMetadataProperty == null) { return; } if (!String.Equals(Convert.ToString(hasStreamMetadataProperty.Value, CultureInfo.InvariantCulture), System.Data.Services.XmlConstants.DataWebAccessDefaultStreamPropertyValue, StringComparison.Ordinal)) { return; } CodeAttributeDeclaration attribute = new CodeAttributeDeclaration( TypeReference.FromString( Utils.WebFrameworkCommonNamespace + "." + "HasStreamAttribute", true)); typeDecl.CustomAttributes.Add(attribute); } /// Edm Member information used for generating attribute, necessary for supporting /// open types which can potentioall not have any member so EdmMember property can be null /// private sealed class EdmInfo { ///Is the given type a complex type public bool IsComplex { get; set; } ///Corresponding EdmMember public EdmMember Member { get; set; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.CodeDom; using System.Collections.Generic; using System.Data.Metadata.Edm; using System.Data.Services.Common; using System.Data.Services.Design; using System.Diagnostics; using System.Globalization; using System.Linq; namespace System.Data.EntityModel.Emitters { ////// Summary description for AttributeEmitter. /// internal sealed partial class AttributeEmitter { private const string _generatorVersion = "1.0.0"; private const string _generatorName = "System.Data.Services.Design"; private static readonly CodeAttributeDeclaration _generatedCodeAttribute = new CodeAttributeDeclaration( new CodeTypeReference(typeof(System.CodeDom.Compiler.GeneratedCodeAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(_generatorName)), new CodeAttributeArgument(new CodePrimitiveExpression(_generatorVersion))); TypeReference _typeReference; internal TypeReference TypeReference { get { return _typeReference; } } internal AttributeEmitter(TypeReference typeReference) { _typeReference = typeReference; } ////// The method to be called to create the type level attributes for the ItemTypeEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. public void EmitTypeAttributes(EntityTypeEmitter emitter, CodeTypeDeclaration typeDecl) { Debug.Assert(emitter != null, "emitter should not be null"); Debug.Assert(typeDecl != null, "typeDecl should not be null"); if (emitter.Generator.Version != DataServiceCodeVersion.V1) { EmitEpmAttributesForEntityType(emitter.Generator.EdmItemCollection, emitter.Item, typeDecl); EmitStreamAttributesForEntityType(emitter.Item, typeDecl); } object[] keys = emitter.Item.KeyMembers.Select(km => (object) km.Name).ToArray(); typeDecl.CustomAttributes.Add(EmitSimpleAttribute(Utils.WebFrameworkCommonNamespace + "." + "DataServiceKeyAttribute", keys)); } ////// The method to be called to create the type level attributes for the StructuredTypeEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. public void EmitTypeAttributes(StructuredTypeEmitter emitter, CodeTypeDeclaration typeDecl) { Debug.Assert(emitter != null, "emitter should not be null"); Debug.Assert(typeDecl != null, "typeDecl should not be null"); // nothing to do here yet } ////// The method to be called to create the type level attributes for the SchemaTypeEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. public void EmitTypeAttributes(SchemaTypeEmitter emitter, CodeTypeDeclaration typeDecl) { Debug.Assert(emitter != null, "emitter should not be null"); Debug.Assert(typeDecl != null, "typeDecl should not be null"); } ////// The method to be called to create the property level attributes for the PropertyEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. /// Additional attributes to emit public void EmitPropertyAttributes(PropertyEmitter emitter, CodeMemberProperty propertyDecl, ListadditionalAttributes) { if (additionalAttributes != null && additionalAttributes.Count > 0) { try { propertyDecl.CustomAttributes.AddRange(additionalAttributes.ToArray()); } catch (ArgumentNullException e) { emitter.Generator.AddError(Strings.InvalidAttributeSuppliedForProperty(emitter.Item.Name), ModelBuilderErrorCode.InvalidAttributeSuppliedForProperty, EdmSchemaErrorSeverity.Error, e); } } } /// /// The method to be called to create the type level attributes for the NestedTypeEmitter /// /// The strongly typed emitter /// The type declaration to add the attribues to. public void EmitTypeAttributes(ComplexTypeEmitter emitter, CodeTypeDeclaration typeDecl) { Debug.Assert(emitter != null, "emitter should not be null"); Debug.Assert(typeDecl != null, "typeDecl should not be null"); // not emitting System.Runtime.Serializaton.DataContractAttribute // not emitting System.Serializable } #region Static Methods ////// /// /// /// ///public CodeAttributeDeclaration EmitSimpleAttribute(string attributeType, params object[] arguments) { CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(TypeReference.FromString(attributeType, true)); AddAttributeArguments(attribute, arguments); return attribute; } /// /// /// /// /// public static void AddAttributeArguments(CodeAttributeDeclaration attribute, object[] arguments) { foreach (object argument in arguments) { CodeExpression expression = argument as CodeExpression; if (expression == null) expression = new CodePrimitiveExpression(argument); attribute.Arguments.Add(new CodeAttributeArgument(expression)); } } ////// Adds an XmlIgnore attribute to the given property declaration. This is /// used to explicitly skip certain properties during XML serialization. /// /// the property to mark with XmlIgnore public void AddIgnoreAttributes(CodeMemberProperty propertyDecl) { // not emitting System.Xml.Serialization.XmlIgnoreAttribute // not emitting System.Xml.Serialization.SoapIgnoreAttribute } ////// Adds an Browsable(false) attribute to the given property declaration. /// This is used to explicitly avoid display property in the PropertyGrid. /// /// the property to mark with XmlIgnore public void AddBrowsableAttribute(CodeMemberProperty propertyDecl) { // not emitting System.ComponentModel.BrowsableAttribute } #endregion ////// Add the GeneratedCode attribute to the code type member /// /// the code type member public static void AddGeneratedCodeAttribute(CodeTypeMember ctm) { ctm.CustomAttributes.Add(_generatedCodeAttribute); } ///Given a type detects if it is an open type or not /// Input type ///true if it is an open type, false otherwise private static bool IsOpenType(StructuralType entityType) { MetadataProperty isOpenTypeProperty = entityType.MetadataProperties.FirstOrDefault(x => x.Name == System.Data.Services.XmlConstants.EdmV1dot2Namespace + ":" + System.Data.Services.XmlConstants.DataWebOpenTypeAttributeName); if (isOpenTypeProperty != null) { bool isOpenType; if (!Boolean.TryParse(Convert.ToString(isOpenTypeProperty.Value, CultureInfo.InvariantCulture), out isOpenType)) { throw new InvalidOperationException(Strings.ObjectContext_OpenTypePropertyValueIsNotCorrect(System.Data.Services.XmlConstants.DataWebOpenTypeAttributeName, entityType.Name)); } return isOpenType; } else { return false; } } ////// Checks if the given path corresponds to some open property on the /// Type to check the path for /// Input property path ////// true if there is some open property corresponding to the path, false otherwise bool IsOpenPropertyOnPath(StructuralType baseEntityType, String sourcePath) { Debug.Assert(baseEntityType != null, "Expecting non-null entity type"); if (String.IsNullOrEmpty(sourcePath)) { return false; } String[] propertyPath = sourcePath.Split('/'); EdmMember entityProperty = baseEntityType.Members.SingleOrDefault(p => p.Name == propertyPath[0]); if (entityProperty == null) { if (baseEntityType.BaseType != null) { return IsOpenPropertyOnPath(baseEntityType.BaseType as StructuralType, sourcePath); } else { return IsOpenType(baseEntityType); } } else { StructuralType entityPropertyType = entityProperty.TypeUsage.EdmType as StructuralType; if (entityPropertyType != null) { return IsOpenPropertyOnPath(entityPropertyType, String.Join("/", propertyPath, 1, propertyPath.Length - 1)); } else { return false; } } } ////// Obtains the entity property corresponding to a given sourcePath /// /// Entity type in which to look for property /// Source Path ///EdmMember object corresponding to the property given through source path private static EdmMember GetEntityPropertyFromEpmPath(StructuralType baseEntityType, String sourcePath) { Debug.Assert(baseEntityType != null, "Expecting non-null entity type"); String[] propertyPath = sourcePath.Split('/'); if (!baseEntityType.Members.Any(p => p.Name == propertyPath[0])) { return baseEntityType.BaseType != null ? GetEntityPropertyFromEpmPath(baseEntityType.BaseType as StructuralType, sourcePath) : null; } else { EdmMember entityProperty = null; foreach (var pathSegment in propertyPath) { if (baseEntityType == null) { return null; } entityProperty = baseEntityType.Members.SingleOrDefault(p => p.Name == pathSegment); if (entityProperty == null) { return null; } baseEntityType = entityProperty.TypeUsage.EdmType as StructuralType; } return entityProperty; } } ////// Returns a sequence of attributes corresponding to a complex type with recursion /// /// Complex typed property /// Source path /// Target path /// Namespace prefix /// Namespace Uri /// KeepInContent setting ///Sequence of entity property mapping information for complex type properties private static IEnumerableGetEpmAttrsFromComplexProperty( EdmMember complexProperty, String epmSourcePath, String epmTargetPath, String epmNsPrefix, String epmNsUri, bool epmKeepContent) { Debug.Assert(complexProperty != null, "Expecting non-null complex property"); ComplexType complexType = complexProperty.TypeUsage.EdmType as ComplexType; if (complexType == null) { throw new ArgumentException(Strings.ExpectingComplexTypeForMember(complexProperty.Name, complexProperty.DeclaringType.Name)); } foreach (EdmMember subProperty in complexType.Properties) { String sourcePath = epmSourcePath + "/" + subProperty.Name; String targetPath = epmTargetPath + "/" + subProperty.Name; if (subProperty.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType) { foreach (EntityPropertyMappingAttribute epmAttr in GetEpmAttrsFromComplexProperty(subProperty, sourcePath, targetPath, epmNsPrefix, epmNsUri, epmKeepContent)) { yield return epmAttr; } } else { yield return new EntityPropertyMappingAttribute( sourcePath, targetPath, epmNsPrefix, epmNsUri, epmKeepContent); } } } /// /// Given a resource type, builds the EntityPropertyMappingInfo for each EntityPropertyMappingAttribute on it /// /// EFx metadata item collection that has been loaded /// Entity type for which EntityPropertyMappingAttribute discovery is happening /// Type declaration to add the attributes to private void EmitEpmAttributesForEntityType(EdmItemCollection itemCollection, EntityType entityType, CodeTypeDeclaration typeDecl) { // Get epm information provided at the entity type declaration level IEnumerableextendedProperties = entityType.MetadataProperties.Where(mp => mp.PropertyKind == PropertyKind.Extended); foreach (EpmPropertyInformation propertyInformation in GetEpmPropertyInformation(extendedProperties, entityType.Name, null)) { EdmMember redefinedProperty = GetEntityPropertyFromEpmPath(entityType, propertyInformation.SourcePath); if (redefinedProperty == null) { if (IsOpenPropertyOnPath(entityType, propertyInformation.SourcePath)) { EmitEpmAttributeForEntityProperty( propertyInformation, new EdmInfo { IsComplex = false, Member = null }, typeDecl); } else { throw new InvalidOperationException(Strings.ObjectContext_UnknownPropertyNameInEpmAttributesType(propertyInformation.SourcePath, entityType.Name)); } } else { EmitEpmAttributeForEntityProperty( propertyInformation, new EdmInfo { IsComplex = redefinedProperty.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, Member = redefinedProperty }, typeDecl); } } // Get epm information provided at the entity type property level foreach (EdmMember member in entityType.Members.Where(m => m.DeclaringType == entityType)) { EdmMember entityProperty = entityType.Properties.SingleOrDefault(p => p.DeclaringType == entityType && p.Name == member.Name); IEnumerable extendedMemberProperties = member.MetadataProperties.Where(mdp => mdp.PropertyKind == PropertyKind.Extended); foreach (EpmPropertyInformation propertyInformation in GetEpmPropertyInformation(extendedMemberProperties, entityType.Name, member.Name)) { EdmMember entityPropertyCurrent = entityProperty; if (entityProperty.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType && propertyInformation.PathGiven) { String originalPath = propertyInformation.SourcePath; propertyInformation.SourcePath = entityProperty.Name + "/" + propertyInformation.SourcePath; entityPropertyCurrent = GetEntityPropertyFromEpmPath(entityType, propertyInformation.SourcePath); if (entityPropertyCurrent == null) { if (IsOpenPropertyOnPath(entityProperty.TypeUsage.EdmType as StructuralType, originalPath)) { EmitEpmAttributeForEntityProperty( propertyInformation, new EdmInfo { IsComplex = false, Member = null }, typeDecl); continue; } else { throw new InvalidOperationException(Strings.ObjectContext_UnknownPropertyNameInEpmAttributesMember(originalPath, member.Name, entityType.Name)); } } } EmitEpmAttributeForEntityProperty( propertyInformation, new EdmInfo { IsComplex = entityPropertyCurrent.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, Member = entityPropertyCurrent }, typeDecl); } } } /// /// Given a resource type and its resource proeperty builds the EntityPropertyMappingInfo for the EntityPropertyMappingAttribute on it /// /// EPM information for current property /// Property for which to get the information /// Type declaration to add the attributes to private void EmitEpmAttributeForEntityProperty( EpmPropertyInformation propertyInformation, EdmInfo entityProperty, CodeTypeDeclaration typeDecl) { if (propertyInformation.IsAtom) { if (entityProperty.IsComplex) { throw new InvalidOperationException(Strings.ObjectContext_SyndicationMappingForComplexPropertiesNotAllowed); } else { EntityPropertyMappingAttribute epmAttr = new EntityPropertyMappingAttribute( propertyInformation.SourcePath, propertyInformation.SyndicationItem, propertyInformation.ContentKind, propertyInformation.KeepInContent); this.AddEpmAttributeToTypeDeclaration(epmAttr, typeDecl); } } else { if (entityProperty.IsComplex) { foreach (EntityPropertyMappingAttribute epmAttr in GetEpmAttrsFromComplexProperty( entityProperty.Member, propertyInformation.SourcePath, propertyInformation.TargetPath, propertyInformation.NsPrefix, propertyInformation.NsUri, propertyInformation.KeepInContent)) { this.AddEpmAttributeToTypeDeclaration(epmAttr, typeDecl); } } else { EntityPropertyMappingAttribute epmAttr = new EntityPropertyMappingAttribute( propertyInformation.SourcePath, propertyInformation.TargetPath, propertyInformation.NsPrefix, propertyInformation.NsUri, propertyInformation.KeepInContent); this.AddEpmAttributeToTypeDeclaration(epmAttr, typeDecl); } } } ///Creates an EntityPropertyMappingAttribute and adds it to the /// Attribute to add /// Type declaration for which the attribute is generated private void AddEpmAttributeToTypeDeclaration(EntityPropertyMappingAttribute epmAttr, CodeTypeDeclaration typeDecl) { if (epmAttr.TargetSyndicationItem != SyndicationItemProperty.CustomProperty) { var syndicationItem = new CodeFieldReferenceExpression( new CodeTypeReferenceExpression(typeof(SyndicationItemProperty)), epmAttr.TargetSyndicationItem.ToString()); var contentKind = new CodeFieldReferenceExpression( new CodeTypeReferenceExpression(typeof(SyndicationTextContentKind)), epmAttr.TargetTextContentKind.ToString()); CodeAttributeDeclaration attribute = new CodeAttributeDeclaration( TypeReference.FromString( Utils.WebFrameworkCommonNamespace + "." + "EntityPropertyMappingAttribute", true)); AddAttributeArguments(attribute, new object[] { epmAttr.SourcePath, syndicationItem, contentKind, epmAttr.KeepInContent }); typeDecl.CustomAttributes.Add(attribute); } else { CodeAttributeDeclaration attribute = new CodeAttributeDeclaration( TypeReference.FromString( Utils.WebFrameworkCommonNamespace + "." + "EntityPropertyMappingAttribute", true)); AddAttributeArguments(attribute, new object[] { epmAttr.SourcePath, epmAttr.TargetPath, epmAttr.TargetNamespacePrefix, epmAttr.TargetNamespaceUri, epmAttr.KeepInContent }); typeDecl.CustomAttributes.Add(attribute); } } ////// Given a resource type, generates the HasStreamAttribute for it /// /// Entity type for which HasStreamAttribute discovery is happening /// Type declaration to add the attributes to private void EmitStreamAttributesForEntityType(EntityType entityType, CodeTypeDeclaration typeDecl) { IEnumerablehasStreamMetadataProperties = entityType.MetadataProperties.Where(mp => mp.PropertyKind == PropertyKind.Extended && mp.Name == System.Data.Services.XmlConstants.DataWebMetadataNamespace + ":" + System.Data.Services.XmlConstants.DataWebAccessHasStreamAttribute); MetadataProperty hasStreamMetadataProperty = null; foreach (MetadataProperty p in hasStreamMetadataProperties) { if (hasStreamMetadataProperty != null) { throw new InvalidOperationException( Strings.ObjectContext_MultipleValuesForSameExtendedAttributeType( System.Data.Services.XmlConstants.DataWebAccessHasStreamAttribute, entityType.Name)); } hasStreamMetadataProperty = p; } if (hasStreamMetadataProperty == null) { return; } if (!String.Equals(Convert.ToString(hasStreamMetadataProperty.Value, CultureInfo.InvariantCulture), System.Data.Services.XmlConstants.DataWebAccessDefaultStreamPropertyValue, StringComparison.Ordinal)) { return; } CodeAttributeDeclaration attribute = new CodeAttributeDeclaration( TypeReference.FromString( Utils.WebFrameworkCommonNamespace + "." + "HasStreamAttribute", true)); typeDecl.CustomAttributes.Add(attribute); } /// Edm Member information used for generating attribute, necessary for supporting /// open types which can potentioall not have any member so EdmMember property can be null /// private sealed class EdmInfo { ///Is the given type a complex type public bool IsComplex { get; set; } ///Corresponding EdmMember public EdmMember Member { get; set; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EntityClientCacheKey.cs
- SpeechAudioFormatInfo.cs
- GenerateScriptTypeAttribute.cs
- WpfKnownTypeInvoker.cs
- RowUpdatedEventArgs.cs
- ContractSearchPattern.cs
- RectValueSerializer.cs
- PenThreadWorker.cs
- HyperLink.cs
- DBSqlParserColumnCollection.cs
- EdmType.cs
- FunctionParameter.cs
- UnsupportedPolicyOptionsException.cs
- DeviceSpecificDialogCachedState.cs
- TypeHelper.cs
- Int32Rect.cs
- EnlistmentState.cs
- UdpMessageProperty.cs
- ActivityTypeCodeDomSerializer.cs
- CriticalFileToken.cs
- BitmapPalettes.cs
- DecoderReplacementFallback.cs
- RepeaterItemCollection.cs
- OdbcStatementHandle.cs
- StyleCollection.cs
- WindowsListViewItem.cs
- DocumentOrderQuery.cs
- MessageSecurityException.cs
- XmlnsDictionary.cs
- MetadataItemCollectionFactory.cs
- EntityContainerEmitter.cs
- ParameterModifier.cs
- MetadataUtilsSmi.cs
- HelpKeywordAttribute.cs
- OneOfConst.cs
- StyleSelector.cs
- BatchParser.cs
- EventRouteFactory.cs
- ObjectItemCollection.cs
- HttpHandlerActionCollection.cs
- SafeEventLogReadHandle.cs
- DataServiceRequestOfT.cs
- ComponentConverter.cs
- CloudCollection.cs
- PropertyDescriptorCollection.cs
- DataServiceStreamResponse.cs
- ServiceHostFactory.cs
- IgnoreDataMemberAttribute.cs
- DataViewManagerListItemTypeDescriptor.cs
- RetrieveVirtualItemEventArgs.cs
- ColorDialog.cs
- QueryableFilterUserControl.cs
- ControlValuePropertyAttribute.cs
- ParameterDataSourceExpression.cs
- TextBoxAutomationPeer.cs
- Stackframe.cs
- XmlBindingWorker.cs
- AutomationIdentifierGuids.cs
- FixedPosition.cs
- ValidatingReaderNodeData.cs
- ACE.cs
- Button.cs
- XmlUtil.cs
- ZoneButton.cs
- TablePattern.cs
- CanExpandCollapseAllConverter.cs
- SourceLineInfo.cs
- GregorianCalendar.cs
- DataMemberConverter.cs
- SqlXmlStorage.cs
- ZoneIdentityPermission.cs
- NumberSubstitution.cs
- TextReader.cs
- RepeatBehavior.cs
- Point.cs
- wgx_sdk_version.cs
- XPathChildIterator.cs
- _UriTypeConverter.cs
- CommonXSendMessage.cs
- TimelineGroup.cs
- FilteredAttributeCollection.cs
- FileDialog.cs
- ExpressionBuilderCollection.cs
- ProviderMetadataCachedInformation.cs
- CapiNative.cs
- ViewPort3D.cs
- TextBox.cs
- IntegerFacetDescriptionElement.cs
- TypedTableBase.cs
- InvalidPrinterException.cs
- codemethodreferenceexpression.cs
- ExternalCalls.cs
- XmlSchemaSubstitutionGroup.cs
- DecimalAnimationUsingKeyFrames.cs
- ExpressionVisitorHelpers.cs
- CreatingCookieEventArgs.cs
- SafeBuffer.cs
- ResXResourceWriter.cs
- Grid.cs
- AsyncDataRequest.cs