NavigationPropertyEmitter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataWeb / Design / system / Data / EntityModel / Emitters / NavigationPropertyEmitter.cs / 4 / NavigationPropertyEmitter.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.CodeDom; 
using System.Collections.Generic;
using System.Data.Services.Design;
using System.Data.Metadata.Edm;
using System.Diagnostics; 

namespace System.Data.EntityModel.Emitters 
{ 
    /// 
    /// Summary description for NavigationPropertyEmitter. 
    /// 
    internal sealed class NavigationPropertyEmitter : PropertyEmitterBase
    {
        private const string ValuePropertyName = "Value"; 

        ///  
        /// 
        /// 
        ///  
        /// 
        public NavigationPropertyEmitter(ClientApiGenerator generator, NavigationProperty navigationProperty, bool declaringTypeUsesStandardBaseType)
            : base(generator, navigationProperty, declaringTypeUsesStandardBaseType)
        { 
        }
 
        ///  
        /// Generate the navigation property
        ///  
        /// The type to add the property to.
        protected override void EmitProperty(CodeTypeDeclaration typeDecl)
        {
            EmitNavigationProperty(typeDecl); 
        }
 
        ///  
        /// Generate the navigation property specified
        ///  
        /// The type to add the property to.
        private void EmitNavigationProperty(CodeTypeDeclaration typeDecl)
        {
            // create a regular property 
            CodeMemberProperty property = EmitNavigationProperty(Item.ToEndMember);
            typeDecl.Members.Add(property); 
 
            EmitField(typeDecl, GetReturnType(Item.ToEndMember), Item.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
        } 

        private void EmitField(CodeTypeDeclaration typeDecl, CodeTypeReference fieldType, bool hasDefault)
        {
            CodeMemberField memberField = new CodeMemberField(fieldType, Utils.FieldNameFromPropName(Item.Name)); 
            memberField.Attributes = MemberAttributes.Private;
            if (hasDefault) 
            { 
                memberField.InitExpression = new CodeObjectCreateExpression(fieldType);
            } 
            typeDecl.Members.Add(memberField);
        }

        ///  
        /// Generate a navigation property
        ///  
        /// the other end 
        /// True to emit Reference navigation property
        /// the generated property 
        private CodeMemberProperty EmitNavigationProperty(RelationshipEndMember target)
        {
            CodeTypeReference typeRef = GetReturnType(target);
 
            // raise the PropertyGenerated event
            PropertyGeneratedEventArgs eventArgs = new PropertyGeneratedEventArgs(Item, 
                                                                                  null, // no backing field 
                                                                                  typeRef);
            this.Generator.RaisePropertyGeneratedEvent(eventArgs); 

            // [System.ComponentModel.Browsable(false)]
            // public TargetType TargetName
            // public EntityReference TargetName 
            // or
            // public EntityCollection TargetNames 
            CodeMemberProperty property = new CodeMemberProperty(); 

            // Only reference navigation properties are currently currently supported with XML serialization 
            // and thus we should use the XmlIgnore and SoapIgnore attributes on other property types.
            AttributeEmitter.AddIgnoreAttributes(property);

            AttributeEmitter.AddBrowsableAttribute(property); 

            CommentEmitter.EmitSummaryComments(Item, property.Comments); 
 
            property.Name = Item.Name;
 
            if (eventArgs.ReturnType != null && !eventArgs.ReturnType.Equals(typeRef))
            {
                property.Type = eventArgs.ReturnType;
            } 
            else
            { 
                property.Type = typeRef; 
            }
 
            property.Attributes = MemberAttributes.Final;

            CodeExpression getMethod = EmitGetMethod(target);
            CodeExpression getReturnExpression; 

            if (target.RelationshipMultiplicity != RelationshipMultiplicity.Many) 
            { 
                property.Attributes |= AccessibilityFromGettersAndSetters(Item);
 
                // insert user-supplied Set code here, before the assignment
                //
                List additionalSetStatements = eventArgs.AdditionalSetStatements;
                if (additionalSetStatements != null && additionalSetStatements.Count > 0) 
                {
                    try 
                    { 
                        property.SetStatements.AddRange(additionalSetStatements.ToArray());
                    } 
                    catch (ArgumentNullException e)
                    {
                        Generator.AddError(Strings.InvalidSetStatementSuppliedForProperty(Item.Name),
                                           ModelBuilderErrorCode.InvalidSetStatementSuppliedForProperty, 
                                           EdmSchemaErrorSeverity.Error,
                                           e); 
                    } 
                }
 
                CodeExpression valueRef = new CodePropertySetValueReferenceExpression();
                if (typeRef != eventArgs.ReturnType)
                {
                    // we need to cast to the actual type 
                    valueRef = new CodeCastExpression(typeRef, valueRef);
                } 
 

                CodeExpression valueProperty = getMethod; 

                // get
                //     return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference("CSpaceQualifiedRelationshipName", "TargetRoleName").Value;
                getReturnExpression = valueProperty; 

                // set 
                //     ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference("CSpaceQualifiedRelationshipName", "TargetRoleName").Value = value; 
                property.SetStatements.Add(
                    new CodeAssignStatement(valueProperty, valueRef)); 

                // setup the accessibility of the navigation property setter and getter
                MemberAttributes propertyAccessibility = property.Attributes & MemberAttributes.AccessMask;
                PropertyEmitter.AddGetterSetterFixUp(Generator.FixUps, GetFullyQualifiedPropertyName(property.Name), 
                    PropertyEmitter.GetGetterAccessibility(Item), propertyAccessibility, true);
                PropertyEmitter.AddGetterSetterFixUp(Generator.FixUps, GetFullyQualifiedPropertyName(property.Name), 
                    PropertyEmitter.GetSetterAccessibility(Item), propertyAccessibility, false); 

            } 
            else
            {
                property.Attributes |= PropertyEmitter.GetGetterAccessibility(Item);
                // get 
                //     return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection("CSpaceQualifiedRelationshipName", "TargetRoleName");
                getReturnExpression = getMethod; 
 
                // set
                // if (value != null) 
                // {
                //    this =
                // }
                CodeExpression valueRef = new CodePropertySetValueReferenceExpression(); 

                property.SetStatements.Add( 
                    new CodeConditionStatement( 
                        EmitExpressionDoesNotEqualNull(valueRef),
                        new CodeAssignStatement(getMethod, valueRef) 
                    )
                );
            }
 
            // if additional Get statements were specified by the event subscriber, insert them now
            // 
            List additionalGetStatements = eventArgs.AdditionalGetStatements; 
            if (additionalGetStatements != null && additionalGetStatements.Count > 0)
            { 
                try
                {
                    property.GetStatements.AddRange(additionalGetStatements.ToArray());
                } 
                catch (ArgumentNullException ex)
                { 
                    Generator.AddError(Strings.InvalidGetStatementSuppliedForProperty(Item.Name), 
                                       ModelBuilderErrorCode.InvalidGetStatementSuppliedForProperty,
                                       EdmSchemaErrorSeverity.Error, 
                                       ex);
                }
            }
 
            property.GetStatements.Add(new CodeMethodReturnStatement(getReturnExpression));
 
            return property; 
        }
 
        internal static bool IsNameAlreadyAMemberName(StructuralType type, string generatedPropertyName, StringComparison comparison)
        {
            foreach (EdmMember member in type.Members)
            { 
                if (member.DeclaringType == type &&
                    member.Name.Equals(generatedPropertyName, comparison)) 
                { 
                    return true;
                } 
            }

            return false;
        } 

        private string GetFullyQualifiedPropertyName(string propertyName) 
        { 
            return Item.DeclaringType.FullName + "." + propertyName;
        } 

        /// 
        /// Gives the SchemaElement back cast to the most
        /// appropriate type 
        /// 
        private new NavigationProperty Item 
        { 
            get
            { 
                return base.Item as NavigationProperty;
            }
        }
 
        /// 
        /// Get the return type for the get method, given the target end 
        ///  
        /// 
        /// true if the is the return type for a reference property 
        /// the return type for a target
        private CodeTypeReference GetReturnType(RelationshipEndMember target)
        {
            CodeTypeReference returnType = Generator.GetLeastPossibleQualifiedTypeReference(GetEntityType(target)); 

            if (target.RelationshipMultiplicity == RelationshipMultiplicity.Many) 
            { 
                returnType = TypeReference.FrameworkGenericClass("System.Collections.ObjectModel", "Collection", returnType);
            } 

            return returnType;
        }
 
        private static EntityTypeBase GetEntityType(RelationshipEndMember endMember)
        { 
            Debug.Assert((BuiltInTypeKind.RefType == endMember.TypeUsage.EdmType.BuiltInTypeKind), "not a reference type"); 
            EntityTypeBase type = ((RefType)endMember.TypeUsage.EdmType).ElementType;
            return type; 
        }

        /// 
        /// Emit the GetRelatedCollection or GetRelatedReference methods 
        /// 
        /// Target end of the relationship 
        /// Expression to invoke the appropriate method 
        private CodeExpression EmitGetMethod(RelationshipEndMember target)
        { 
            return new CodeFieldReferenceExpression(ThisRef, Utils.FieldNameFromPropName(Item.Name));
        }
    }
} 

// 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.Services.Design;
using System.Data.Metadata.Edm;
using System.Diagnostics; 

namespace System.Data.EntityModel.Emitters 
{ 
    /// 
    /// Summary description for NavigationPropertyEmitter. 
    /// 
    internal sealed class NavigationPropertyEmitter : PropertyEmitterBase
    {
        private const string ValuePropertyName = "Value"; 

        ///  
        /// 
        /// 
        ///  
        /// 
        public NavigationPropertyEmitter(ClientApiGenerator generator, NavigationProperty navigationProperty, bool declaringTypeUsesStandardBaseType)
            : base(generator, navigationProperty, declaringTypeUsesStandardBaseType)
        { 
        }
 
        ///  
        /// Generate the navigation property
        ///  
        /// The type to add the property to.
        protected override void EmitProperty(CodeTypeDeclaration typeDecl)
        {
            EmitNavigationProperty(typeDecl); 
        }
 
        ///  
        /// Generate the navigation property specified
        ///  
        /// The type to add the property to.
        private void EmitNavigationProperty(CodeTypeDeclaration typeDecl)
        {
            // create a regular property 
            CodeMemberProperty property = EmitNavigationProperty(Item.ToEndMember);
            typeDecl.Members.Add(property); 
 
            EmitField(typeDecl, GetReturnType(Item.ToEndMember), Item.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
        } 

        private void EmitField(CodeTypeDeclaration typeDecl, CodeTypeReference fieldType, bool hasDefault)
        {
            CodeMemberField memberField = new CodeMemberField(fieldType, Utils.FieldNameFromPropName(Item.Name)); 
            memberField.Attributes = MemberAttributes.Private;
            if (hasDefault) 
            { 
                memberField.InitExpression = new CodeObjectCreateExpression(fieldType);
            } 
            typeDecl.Members.Add(memberField);
        }

        ///  
        /// Generate a navigation property
        ///  
        /// the other end 
        /// True to emit Reference navigation property
        /// the generated property 
        private CodeMemberProperty EmitNavigationProperty(RelationshipEndMember target)
        {
            CodeTypeReference typeRef = GetReturnType(target);
 
            // raise the PropertyGenerated event
            PropertyGeneratedEventArgs eventArgs = new PropertyGeneratedEventArgs(Item, 
                                                                                  null, // no backing field 
                                                                                  typeRef);
            this.Generator.RaisePropertyGeneratedEvent(eventArgs); 

            // [System.ComponentModel.Browsable(false)]
            // public TargetType TargetName
            // public EntityReference TargetName 
            // or
            // public EntityCollection TargetNames 
            CodeMemberProperty property = new CodeMemberProperty(); 

            // Only reference navigation properties are currently currently supported with XML serialization 
            // and thus we should use the XmlIgnore and SoapIgnore attributes on other property types.
            AttributeEmitter.AddIgnoreAttributes(property);

            AttributeEmitter.AddBrowsableAttribute(property); 

            CommentEmitter.EmitSummaryComments(Item, property.Comments); 
 
            property.Name = Item.Name;
 
            if (eventArgs.ReturnType != null && !eventArgs.ReturnType.Equals(typeRef))
            {
                property.Type = eventArgs.ReturnType;
            } 
            else
            { 
                property.Type = typeRef; 
            }
 
            property.Attributes = MemberAttributes.Final;

            CodeExpression getMethod = EmitGetMethod(target);
            CodeExpression getReturnExpression; 

            if (target.RelationshipMultiplicity != RelationshipMultiplicity.Many) 
            { 
                property.Attributes |= AccessibilityFromGettersAndSetters(Item);
 
                // insert user-supplied Set code here, before the assignment
                //
                List additionalSetStatements = eventArgs.AdditionalSetStatements;
                if (additionalSetStatements != null && additionalSetStatements.Count > 0) 
                {
                    try 
                    { 
                        property.SetStatements.AddRange(additionalSetStatements.ToArray());
                    } 
                    catch (ArgumentNullException e)
                    {
                        Generator.AddError(Strings.InvalidSetStatementSuppliedForProperty(Item.Name),
                                           ModelBuilderErrorCode.InvalidSetStatementSuppliedForProperty, 
                                           EdmSchemaErrorSeverity.Error,
                                           e); 
                    } 
                }
 
                CodeExpression valueRef = new CodePropertySetValueReferenceExpression();
                if (typeRef != eventArgs.ReturnType)
                {
                    // we need to cast to the actual type 
                    valueRef = new CodeCastExpression(typeRef, valueRef);
                } 
 

                CodeExpression valueProperty = getMethod; 

                // get
                //     return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference("CSpaceQualifiedRelationshipName", "TargetRoleName").Value;
                getReturnExpression = valueProperty; 

                // set 
                //     ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference("CSpaceQualifiedRelationshipName", "TargetRoleName").Value = value; 
                property.SetStatements.Add(
                    new CodeAssignStatement(valueProperty, valueRef)); 

                // setup the accessibility of the navigation property setter and getter
                MemberAttributes propertyAccessibility = property.Attributes & MemberAttributes.AccessMask;
                PropertyEmitter.AddGetterSetterFixUp(Generator.FixUps, GetFullyQualifiedPropertyName(property.Name), 
                    PropertyEmitter.GetGetterAccessibility(Item), propertyAccessibility, true);
                PropertyEmitter.AddGetterSetterFixUp(Generator.FixUps, GetFullyQualifiedPropertyName(property.Name), 
                    PropertyEmitter.GetSetterAccessibility(Item), propertyAccessibility, false); 

            } 
            else
            {
                property.Attributes |= PropertyEmitter.GetGetterAccessibility(Item);
                // get 
                //     return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection("CSpaceQualifiedRelationshipName", "TargetRoleName");
                getReturnExpression = getMethod; 
 
                // set
                // if (value != null) 
                // {
                //    this =
                // }
                CodeExpression valueRef = new CodePropertySetValueReferenceExpression(); 

                property.SetStatements.Add( 
                    new CodeConditionStatement( 
                        EmitExpressionDoesNotEqualNull(valueRef),
                        new CodeAssignStatement(getMethod, valueRef) 
                    )
                );
            }
 
            // if additional Get statements were specified by the event subscriber, insert them now
            // 
            List additionalGetStatements = eventArgs.AdditionalGetStatements; 
            if (additionalGetStatements != null && additionalGetStatements.Count > 0)
            { 
                try
                {
                    property.GetStatements.AddRange(additionalGetStatements.ToArray());
                } 
                catch (ArgumentNullException ex)
                { 
                    Generator.AddError(Strings.InvalidGetStatementSuppliedForProperty(Item.Name), 
                                       ModelBuilderErrorCode.InvalidGetStatementSuppliedForProperty,
                                       EdmSchemaErrorSeverity.Error, 
                                       ex);
                }
            }
 
            property.GetStatements.Add(new CodeMethodReturnStatement(getReturnExpression));
 
            return property; 
        }
 
        internal static bool IsNameAlreadyAMemberName(StructuralType type, string generatedPropertyName, StringComparison comparison)
        {
            foreach (EdmMember member in type.Members)
            { 
                if (member.DeclaringType == type &&
                    member.Name.Equals(generatedPropertyName, comparison)) 
                { 
                    return true;
                } 
            }

            return false;
        } 

        private string GetFullyQualifiedPropertyName(string propertyName) 
        { 
            return Item.DeclaringType.FullName + "." + propertyName;
        } 

        /// 
        /// Gives the SchemaElement back cast to the most
        /// appropriate type 
        /// 
        private new NavigationProperty Item 
        { 
            get
            { 
                return base.Item as NavigationProperty;
            }
        }
 
        /// 
        /// Get the return type for the get method, given the target end 
        ///  
        /// 
        /// true if the is the return type for a reference property 
        /// the return type for a target
        private CodeTypeReference GetReturnType(RelationshipEndMember target)
        {
            CodeTypeReference returnType = Generator.GetLeastPossibleQualifiedTypeReference(GetEntityType(target)); 

            if (target.RelationshipMultiplicity == RelationshipMultiplicity.Many) 
            { 
                returnType = TypeReference.FrameworkGenericClass("System.Collections.ObjectModel", "Collection", returnType);
            } 

            return returnType;
        }
 
        private static EntityTypeBase GetEntityType(RelationshipEndMember endMember)
        { 
            Debug.Assert((BuiltInTypeKind.RefType == endMember.TypeUsage.EdmType.BuiltInTypeKind), "not a reference type"); 
            EntityTypeBase type = ((RefType)endMember.TypeUsage.EdmType).ElementType;
            return type; 
        }

        /// 
        /// Emit the GetRelatedCollection or GetRelatedReference methods 
        /// 
        /// Target end of the relationship 
        /// Expression to invoke the appropriate method 
        private CodeExpression EmitGetMethod(RelationshipEndMember target)
        { 
            return new CodeFieldReferenceExpression(ThisRef, Utils.FieldNameFromPropName(Item.Name));
        }
    }
} 

// 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