Esempio n. 1
0
 /// <summary>
 /// Helper method that raises the PropertyGenerated event
 /// </summary>
 /// <param name="eventArgs">The event arguments passed to the subscriber</param>
 internal void RaisePropertyGeneratedEvent(PropertyGeneratedEventArgs eventArgs)
 {
     if (this.OnPropertyGenerated != null)
     {
         this.OnPropertyGenerated(this, eventArgs);
     }
 }
 /// <summary>
 /// Helper method that raises the PropertyGenerated event
 /// </summary>
 /// <param name="eventArgs">The event arguments passed to the subscriber</param>
 internal void RaisePropertyGeneratedEvent(PropertyGeneratedEventArgs eventArgs)
 {
     _generator.RaisePropertyGeneratedEvent(eventArgs);
 }
        private CodeMemberProperty CreateEntitySetProperty(EntitySet set)
        {
            Debug.Assert(set != null, "Property is Null");

            // trying to get
            //
            // [System.ComponentModel.Browsable(false)]
            // public ObjectQuery<Customer> Customers
            // {
            //      get
            //      {
            //          if ((this._Customers == null))
            //          {
            //              this._Customers = base.CreateQuery<Customer>("[Customers]");
            //          }
            //          return this._Customers;
            //      }
            // }
            //
            CodeMemberProperty codeProperty = new CodeMemberProperty();
            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(codeProperty);
            codeProperty.Attributes = MemberAttributes.Final | GetEntitySetPropertyAccessibility(set);
            codeProperty.Name = set.Name;
            codeProperty.HasGet = true;
            codeProperty.HasSet = false;

            // Determine type to use for field/property and name of factory method on ObjectContext
            string typeName = "ObjectQuery";
            string createMethodName = "CreateQuery";
            // When the EntitySet name is used as CommandText, it should be quoted
            string createMethodArgument = "[" + set.Name + "]";

            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);
            codeProperty.Type = TypeReference.AdoFrameworkGenericClass(typeName, genericParameter);
            string fieldName = Utils.FieldNameFromPropName(set.Name);

            // raise the PropertyGenerated event before proceeding further
            PropertyGeneratedEventArgs eventArgs = new PropertyGeneratedEventArgs(set, fieldName, codeProperty.Type);
            Generator.RaisePropertyGeneratedEvent(eventArgs);

            if (eventArgs.ReturnType == null || !eventArgs.ReturnType.Equals(codeProperty.Type))
            {
                throw EDesignUtil.InvalidOperation(Strings.CannotChangePropertyReturnType(set.Name, Item.Name));
            }

            List<CodeAttributeDeclaration> additionalAttributes = eventArgs.AdditionalAttributes;
            if (additionalAttributes != null && additionalAttributes.Count > 0)
            {
                try
                {
                    codeProperty.CustomAttributes.AddRange(additionalAttributes.ToArray());
                }
                catch (ArgumentNullException e)
                {
                    Generator.AddError(Strings.InvalidAttributeSuppliedForProperty(Item.Name),
                                               ModelBuilderErrorCode.InvalidAttributeSuppliedForProperty,
                                               EdmSchemaErrorSeverity.Error,
                                               e);
                }
            }

            // we need to insert user-specified code before other/existing code, including
            // the return statement
            List<CodeStatement> additionalGetStatements = eventArgs.AdditionalGetStatements;

            if (additionalGetStatements != null && additionalGetStatements.Count > 0)
            {
                try
                {
                    codeProperty.GetStatements.AddRange(additionalGetStatements.ToArray());
                }
                catch (ArgumentNullException e)
                {
                    Generator.AddError(Strings.InvalidGetStatementSuppliedForProperty(Item.Name),
                                       ModelBuilderErrorCode.InvalidGetStatementSuppliedForProperty,
                                       EdmSchemaErrorSeverity.Error,
                                       e);
                }
            }

            codeProperty.GetStatements.Add(
                new CodeConditionStatement(
                    EmitExpressionEqualsNull(new CodeFieldReferenceExpression(ThisRef, fieldName)),
                    new CodeAssignStatement(
                        new CodeFieldReferenceExpression(ThisRef, fieldName),
                        new CodeMethodInvokeExpression(
                            new CodeMethodReferenceExpression(
                                new CodeBaseReferenceExpression(),
                                createMethodName,
                                new CodeTypeReference[] { genericParameter }
                            ),
                            new CodePrimitiveExpression(createMethodArgument)
                        )
                    )
                )
            );

            codeProperty.GetStatements.Add(
                new CodeMethodReturnStatement(
                    new CodeFieldReferenceExpression(
                        ThisRef,
                        fieldName
                    )
                )
            );

            // property summary
            CommentEmitter.EmitSummaryComments(set, codeProperty.Comments);

            return codeProperty;
        }
 /// <summary>
 /// Helper method that raises the PropertyGenerated event
 /// </summary>
 /// <param name="eventArgs">The event arguments passed to the subscriber</param>
 internal void RaisePropertyGeneratedEvent(PropertyGeneratedEventArgs eventArgs)
 {
     if (this.OnPropertyGenerated != null)
     {
         this.OnPropertyGenerated(this, eventArgs);
     }
 }
        /// <summary>
        /// Generate a navigation property
        /// </summary>
        /// <param name="target">the other end</param>
        /// <param name="referenceProperty">True to emit Reference navigation property</param>
        /// <returns>the generated property</returns>
        private CodeMemberProperty EmitNavigationProperty(RelationshipEndMember target, bool referenceProperty)
        {
            CodeTypeReference typeRef = GetReturnType(target, referenceProperty);

            // 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<TargetType> TargetName
            // or
            // public EntityCollection<targetType> TargetNames
            CodeMemberProperty property = new CodeMemberProperty();
            if (referenceProperty)
            {
                AttributeEmitter.AddBrowsableAttribute(property);
                Generator.AttributeEmitter.EmitGeneratedCodeAttribute(property);
            }
            else
            {
                Generator.AttributeEmitter.EmitNavigationPropertyAttributes(Generator, target, property, eventArgs.AdditionalAttributes);

                // 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.AddDataMemberAttribute(property);

            CommentEmitter.EmitSummaryComments(Item, property.Comments);

            property.Name = Item.Name;
            if (referenceProperty)
            {
                property.Name += "Reference";
                if (IsNameAlreadyAMemberName(Item.DeclaringType, property.Name, Generator.LanguageAppropriateStringComparer))
                {
                    Generator.AddError(Strings.GeneratedNavigationPropertyNameConflict(Item.Name, Item.DeclaringType.Name, property.Name),
                        ModelBuilderErrorCode.GeneratedNavigationPropertyNameConflict,
                        EdmSchemaErrorSeverity.Error, Item.DeclaringType.FullName, property.Name);
                }
            }

            if (eventArgs.ReturnType != null && !eventArgs.ReturnType.Equals(typeRef))
            {
                property.Type = eventArgs.ReturnType;
            }
            else
            {
                property.Type = typeRef;
            }

            property.Attributes = MemberAttributes.Final;

            CodeMethodInvokeExpression getMethod = EmitGetMethod(target);
            CodeExpression getReturnExpression;

            property.Attributes |= AccessibilityFromGettersAndSetters(Item);
            // 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);

            if (target.RelationshipMultiplicity != RelationshipMultiplicity.Many)
            {
                
                // insert user-supplied Set code here, before the assignment
                //
                List<CodeStatement> additionalSetStatements = eventArgs.AdditionalSetStatements;
                if (additionalSetStatements != null && additionalSetStatements.Count > 0)
                {
                    try
                    {
                        property.SetStatements.AddRange(additionalSetStatements.ToArray());
                    }
                    catch (ArgumentNullException ex)
                    {
                        Generator.AddError(Strings.InvalidSetStatementSuppliedForProperty(Item.Name),
                                           ModelBuilderErrorCode.InvalidSetStatementSuppliedForProperty,
                                           EdmSchemaErrorSeverity.Error,
                                           ex);
                    }
                }

                CodeExpression valueRef =  new CodePropertySetValueReferenceExpression();
                if(typeRef != eventArgs.ReturnType)
                {
                    // we need to cast to the actual type
                    valueRef = new CodeCastExpression(typeRef, valueRef);
                }

                if (referenceProperty)
                {
                    // get
                    //     return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<TTargetEntity>("CSpaceQualifiedRelationshipName", "TargetRoleName");
                    getReturnExpression = getMethod;

                    // set
                    // if (value != null)
                    // {
                    //    ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedReference<TTargetEntity>"CSpaceQualifiedRelationshipName", "TargetRoleName", value);
                    // }
                    
                    CodeMethodReferenceExpression initReferenceMethod = new CodeMethodReferenceExpression();
                    initReferenceMethod.MethodName = "InitializeRelatedReference";

                    initReferenceMethod.TypeArguments.Add(Generator.GetLeastPossibleQualifiedTypeReference(GetEntityType(target)));
                    initReferenceMethod.TargetObject = new CodePropertyReferenceExpression(
                        new CodeCastExpression(TypeReference.IEntityWithRelationshipsTypeBaseClass, ThisRef),
                        "RelationshipManager");

                    // relationships aren't backed by types so we won't map the namespace
                    // or we can't find the relationship again later
                    string cspaceNamespaceNameQualifiedRelationshipName = target.DeclaringType.FullName;
                                         
                    property.SetStatements.Add(
                        new CodeConditionStatement(
                            EmitExpressionDoesNotEqualNull(valueRef),                           
                            new CodeExpressionStatement(
                                new CodeMethodInvokeExpression(
                                initReferenceMethod, new CodeExpression[] {
                                    new CodePrimitiveExpression(cspaceNamespaceNameQualifiedRelationshipName), new CodePrimitiveExpression(target.Name), valueRef}))));
                }
                else
                {
                    CodePropertyReferenceExpression valueProperty = new CodePropertyReferenceExpression(getMethod, ValuePropertyName);

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

                    // set
                    //     ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<TTargetEntity>("CSpaceQualifiedRelationshipName", "TargetRoleName").Value = value;
                    property.SetStatements.Add(
                        new CodeAssignStatement(valueProperty, valueRef));
                }
            }
            else
            {
                // get
                //     return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<TTargetEntity>("CSpaceQualifiedRelationshipName", "TargetRoleName");
                getReturnExpression = getMethod;

                // set
                // if (value != null)
                // {
                //    ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<TTargetEntity>"CSpaceQualifiedRelationshipName", "TargetRoleName", value);
                // }
                CodeExpression valueRef = new CodePropertySetValueReferenceExpression();
                
                CodeMethodReferenceExpression initCollectionMethod = new CodeMethodReferenceExpression();
                initCollectionMethod.MethodName = "InitializeRelatedCollection";

                initCollectionMethod.TypeArguments.Add(Generator.GetLeastPossibleQualifiedTypeReference(GetEntityType(target)));
                initCollectionMethod.TargetObject = new CodePropertyReferenceExpression(
                    new CodeCastExpression(TypeReference.IEntityWithRelationshipsTypeBaseClass, ThisRef),
                    "RelationshipManager");

                // relationships aren't backed by types so we won't map the namespace
                // or we can't find the relationship again later
                string cspaceNamespaceNameQualifiedRelationshipName = target.DeclaringType.FullName;

                property.SetStatements.Add(
                    new CodeConditionStatement(
                        EmitExpressionDoesNotEqualNull(valueRef),
                        new CodeExpressionStatement(
                            new CodeMethodInvokeExpression(
                            initCollectionMethod, new CodeExpression[] {
                                    new CodePrimitiveExpression(cspaceNamespaceNameQualifiedRelationshipName), new CodePrimitiveExpression(target.Name), valueRef}))));

            }

            // if additional Get statements were specified by the event subscriber, insert them now
            //
            List<CodeStatement> 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;
        }