AttributeEmitter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / 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, 
                                           List additionalAttributes)
        { 
            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 IEnumerable GetEpmAttrsFromComplexProperty(
            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
            IEnumerable extendedProperties = 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)
        { 
            IEnumerable hasStreamMetadataProperties = 
                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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK