PropertyEmitter.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 / PropertyEmitter.cs / 1305376 / PropertyEmitter.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.Design;
using System.Data.Services.Design.Common; 
using System.Diagnostics;
using System.Globalization; 
 
namespace System.Data.EntityModel.Emitters
{ 
    /// 
    ///
    /// 
    internal sealed class PropertyEmitter : PropertyEmitterBase 
    {
        private CodeFieldReferenceExpression _fieldRef; 
        private CodeFieldReferenceExpression _complexPropertyInitializedFieldRef; 

        // statics 
        private const string NestedStoreObjectCollection = "InlineObjectCollection";
        private const string DetachFromParentMethodName = "DetachFromParent";

        #region Public Methods 

        ///  
        /// 
        /// 
        ///  
        /// 
        public PropertyEmitter(ClientApiGenerator generator, EdmProperty property, bool declaringTypeUsesStandardBaseType)
            : base(generator, property, declaringTypeUsesStandardBaseType)
        { 
        }
 
        ///  
        /// Emit the declaration of the property for the class.
        ///  
        /// The Property declaration pieces of the CodeDom.
        public CodeMemberProperty EmitPropertyDeclaration(CodeTypeReference propertyReturnType)
        {
            MemberAttributes scope = AccessibilityFromGettersAndSetters(Item); 
            CodeMemberProperty memberProperty = EmitPropertyDeclaration(scope, propertyReturnType, IsVirtualProperty, HidesBaseClassProperty);
 
            memberProperty.HasSet = true; 
            memberProperty.HasGet = true;
 
            return memberProperty;
        }

        ///  
        /// Main method for Emitting property code.
        ///  
        /// The CodeDom representation of the type that the property is being added to. 
        protected override void EmitProperty(CodeTypeDeclaration typeDecl)
        { 
            CodeTypeReference typeRef = PropertyType;

            // raise the PropertyGenerated event
            // 
            PropertyGeneratedEventArgs eventArgs = new PropertyGeneratedEventArgs(Item, FieldName, typeRef);
            this.Generator.RaisePropertyGeneratedEvent(eventArgs); 
 
            // the event subscriber cannot change the return type of the property
            // 
            DisallowReturnTypeChange(typeRef, eventArgs.ReturnType);

            CodeMemberProperty memberProperty = EmitPropertyDeclaration(eventArgs.ReturnType);
            if (memberProperty == null) 
            {
                return; 
            } 

            EmitCustomAttributes(memberProperty, eventArgs.AdditionalAttributes); 

            EmitPropertyGetter(memberProperty, eventArgs.AdditionalGetStatements);
            EmitPropertySetter(memberProperty, eventArgs.AdditionalSetStatements, eventArgs.AdditionalAfterSetStatements);
 
            typeDecl.Members.Add(memberProperty);
 
            EmitField(typeDecl, eventArgs.ReturnType); 

            EmitPropertyOnChangePartialMethods(typeDecl, eventArgs.ReturnType); 
        }

        /// 
        /// Emit these methods as "abstract" and fix them up later to be "partial". 
        /// CodeDOM does not support partial methods
        ///  
        ///  
        private void EmitPropertyOnChangePartialMethods(CodeTypeDeclaration typeDecl, CodeTypeReference returnType)
        { 
            CodeMemberMethod onChangingDomMethod = new CodeMemberMethod();
            onChangingDomMethod.Name = OnChangingPartialMethodName(PropertyName);
            onChangingDomMethod.ReturnType = new CodeTypeReference(typeof(void));
            onChangingDomMethod.Attributes = MemberAttributes.Abstract | MemberAttributes.Public; 
            onChangingDomMethod.Parameters.Add(new CodeParameterDeclarationExpression(returnType, "value"));
            typeDecl.Members.Add(onChangingDomMethod); 
 
            CodeMemberMethod onChangedDomMethod = new CodeMemberMethod();
            onChangedDomMethod.Name = OnChangedPartialMethodName(PropertyName); 
            onChangedDomMethod.ReturnType = new CodeTypeReference(typeof(void));
            onChangedDomMethod.Attributes = MemberAttributes.Abstract | MemberAttributes.Public;
            typeDecl.Members.Add(onChangedDomMethod);
 
            Generator.FixUps.Add(new FixUp(PropertyClassName + "." + OnChangingPartialMethodName(PropertyName), FixUpType.MarkAbstractMethodAsPartial));
            Generator.FixUps.Add(new FixUp(PropertyClassName + "." + OnChangedPartialMethodName(PropertyName), FixUpType.MarkAbstractMethodAsPartial)); 
        } 

        private void EmitField(CodeTypeDeclaration typeDecl, CodeTypeReference fieldType) 
        {
            CodeMemberField memberField = new CodeMemberField(fieldType, FieldName);
            memberField.Attributes = MemberAttributes.Private;
            if (HasDefault(Item)) 
            {
                memberField.InitExpression = GetDefaultValueExpression(Item); 
            } 

            AttributeEmitter.AddGeneratedCodeAttribute(memberField); 

            typeDecl.Members.Add(memberField);

            if (TypeSemantics.IsComplexType(Item.TypeUsage)) 
            {
                CodeMemberField complexInitField = new CodeMemberField(TypeReference.ForType(typeof(bool)), ComplexPropertyInitializedFieldName); 
                complexInitField.Attributes = MemberAttributes.Private; 
                AttributeEmitter.AddGeneratedCodeAttribute(complexInitField);
                typeDecl.Members.Add(complexInitField); 
            }
        }

        #endregion 
        #region Public Properties
 
        ///  
        ///
        ///  
        public CodeTypeReference PropertyType
        {
            get
            { 
                CodeTypeReference typeRef = GetType(Item, false);
                return typeRef; 
            } 
        }
 
        public new EdmProperty Item
        {
            get
            { 
                return base.Item as EdmProperty;
            } 
        } 

        #endregion 
        #region Internal Methods
        /// 
        /// Name of the associated Entity property for Ref(T) properties
        ///  
        public string EntityPropertyName
        { 
            get 
            {
                return Item.Name; 
            }
        }

        #endregion 
        #region Private Methods
        ///  
        /// 
        /// 
        ///  
        /// Additional attributes to emit
        private void EmitCustomAttributes(CodeMemberProperty memberProperty,
                                          List additionalAttributes)
        { 
            AttributeEmitter.AddGeneratedCodeAttribute(memberProperty);
            Generator.AttributeEmitter.EmitPropertyAttributes(this, memberProperty, additionalAttributes); 
        } 

        private void EmitPropertyGetter(CodeMemberProperty memberProperty, List additionalGetStatements) 
        {
            CodeStatementCollection statements = memberProperty.GetStatements;

            // we need to insert user-specified code before other/existing code, including 
            // the return statement
            if (additionalGetStatements != null && additionalGetStatements.Count > 0) 
            { 
                try
                { 
                    CodeStatementCollection getStatements = new CodeStatementCollection();
                    getStatements.AddRange(additionalGetStatements.ToArray());
                    if (statements != null && statements.Count > 0)
                    { 
                        getStatements.AddRange(statements);
                    } 
                    statements.Clear(); 
                    statements.AddRange(getStatements);
                } 
                catch (ArgumentNullException e)
                {
                    Generator.AddError(Strings.InvalidGetStatementSuppliedForProperty(Item.Name),
                                       ModelBuilderErrorCode.InvalidGetStatementSuppliedForProperty, 
                                       EdmSchemaErrorSeverity.Error,
                                       e); 
                } 
            }
 
            MemberAttributes access = memberProperty.Attributes & MemberAttributes.AccessMask;

            AddGetterSetterFixUp(Generator.FixUps, PropertyFQName, GetGetterAccessibility(Item), access, true);
 
            EmitPropertyGetterBody(statements);
        } 
 
        /// 
        /// 
        /// 
        /// 
        private void EmitPropertyGetterBody(CodeStatementCollection statements)
        { 
            // If the SchemaElement.Type isn't a ComplexType it better be PrimitiveType.
            if (Helper.IsComplexType(Item.TypeUsage.EdmType)) 
            { 
                //Since Complex Collections are not supported by
                //the stack, we don't need to do anything special 
                //like doing an Attach or Detatch like the way we do for complex types.
                if (GetCollectionKind(Item.TypeUsage) == CollectionKind.None)
                {
                    // if ((_field == null)) && 
                    //     (_fieldInitialized == false))
                    // { 
                    //    _field = new (); 
                    //    _fieldInitialized = true;
                    // } 
                    statements.Add(
                        // if
                        new CodeConditionStatement(
 
                            new CodeBinaryOperatorExpression(
                        // (_field == null)) 
                                EmitExpressionEqualsNull(FieldRef), 
                                CodeBinaryOperatorType.BooleanAnd,
 
                                // (_fieldInitialized != true)
                                new CodeBinaryOperatorExpression(
                                    ComplexPropertyInitializedFieldRef,
                                    CodeBinaryOperatorType.IdentityInequality, 
                                    new CodePrimitiveExpression(true)
                                ) 
                            ), 
                        // { _field = new ();
                            new CodeAssignStatement(FieldRef, 
                                new CodeObjectCreateExpression(PropertyType)
                            ),
                        // _fieldInitialized = true; }
                            new CodeAssignStatement( 
                                ComplexPropertyInitializedFieldRef,
                                new CodePrimitiveExpression(true) 
                            ) 
                        )
                    ); 
                }
                // return _field;
                statements.Add(new CodeMethodReturnStatement(FieldRef));
            } 
            else
            { 
                PrimitiveType primitiveType = Item.TypeUsage.EdmType as PrimitiveType; 
                if (primitiveType != null && primitiveType.ClrEquivalentType == typeof(byte[]))
                { 
                    // if (_field != null) { return _filed.Clone(); } else { return null; }
                    statements.Add(
                        // if
                        new CodeConditionStatement( 
                        // (_field == null) * (NOT _field Is Nothing)
                            EmitExpressionDoesNotEqualNull(FieldRef), 
                            new CodeStatement[] { 
                                // { _field = new ();
                                new CodeMethodReturnStatement( 
                                    new CodeCastExpression(typeof(byte[]),
                                        new CodeMethodInvokeExpression(FieldRef, "Clone")
                                    )
                                ) 
                            },
                            new CodeStatement[] { 
                                // return null * return Nothing 
                                new CodeMethodReturnStatement(
                                    NullExpression 
                                )
                            }
                        )
                    ); 
                }
                else 
                { 
                    // for everything else just return the field.
                    statements.Add(new CodeMethodReturnStatement(FieldRef)); 
                }
            }
        }
 

        ///  
        /// 
        /// 
        ///  
        /// Additional statements to emit
        private void EmitPropertySetter(CodeMemberProperty memberProperty, List additionalSetStatements, List additionalAfterSetStatements)
        {
            CodeStatementCollection statements = memberProperty.SetStatements; 

            MemberAttributes access = memberProperty.Attributes & MemberAttributes.AccessMask; 
 
            AddGetterSetterFixUp(Generator.FixUps, PropertyFQName, GetSetterAccessibility(Item), access, false);
            EmitPropertySetterBody(statements, additionalSetStatements, additionalAfterSetStatements); 
        }

        /// 
        /// This is a control function to delegate the creation of the 
        /// setter statments to the correct code path
        ///  
        /// The collection that the setter statements should be added to. 
        /// Additional statements to emit
        private void EmitPropertySetterBody(CodeStatementCollection statements, List additionalSetStatements, List additionalAfterSetStatements) 
        {
            // Invoke the partial method "On[PropertyName]Changing();
            statements.Add(
                new CodeMethodInvokeExpression( 
                    ThisRef,
                    OnChangingPartialMethodName(PropertyName), new CodePropertySetValueReferenceExpression())); 
 
            // insert additional statements following the PropertyChanging event
            if (additionalSetStatements != null && additionalSetStatements.Count > 0) 
            {
                try
                {
                    statements.AddRange(additionalSetStatements.ToArray()); 
                }
                catch (ArgumentNullException e) 
                { 
                    Generator.AddError(Strings.InvalidSetStatementSuppliedForProperty(Item.Name),
                                       ModelBuilderErrorCode.InvalidSetStatementSuppliedForProperty, 
                                       EdmSchemaErrorSeverity.Error,
                                       e);
                }
            } 

            // this.fieldName = value; 
            statements.Add( 
                new CodeAssignStatement(
                        FieldRef, 
                        new CodePropertySetValueReferenceExpression()));

            if (Helper.IsComplexType(Item.TypeUsage.EdmType))
            { 
                if (GetCollectionKind(Item.TypeUsage) == CollectionKind.None)
                { 
                    // this._complexPropertyInitialized = true; 
                    statements.Add(
                        new CodeAssignStatement( 
                            ComplexPropertyInitializedFieldRef,
                            new CodePrimitiveExpression(true)));
                }
            } 

            // Invoke the partial method "On[PropertyName]Changed(); 
            statements.Add( 
                new CodeMethodInvokeExpression(
                    ThisRef, 
                    OnChangedPartialMethodName(PropertyName)));

            // insert additional statements following the PropertyChanged event
            if (additionalAfterSetStatements != null && additionalAfterSetStatements.Count > 0) 
            {
                try 
                { 
                    statements.AddRange(additionalAfterSetStatements.ToArray());
                } 
                catch (ArgumentNullException e)
                {
                    Generator.AddError(Strings.InvalidSetStatementSuppliedForProperty(Item.Name),
                                       ModelBuilderErrorCode.InvalidSetStatementSuppliedForProperty, 
                                       EdmSchemaErrorSeverity.Error,
                                       e); 
                } 
            }
        } 

        /// 
        /// Do the fixups to allow get and set statements in properties
        /// to have different accessibility than the property itself. 
        /// 
        /// The accessibility for the getter or setter 
        /// The property's accessibility 
        /// True if this is a getter, false if a setter
        internal static void AddGetterSetterFixUp(FixUpCollection fixups, string propertyFqName, MemberAttributes accessibility, MemberAttributes propertyAccessibility, bool isGetter) 
        {
            Debug.Assert(GetAccessibilityRank(accessibility) >= 0, "bad accessibility");

            // Private 
            if (accessibility == MemberAttributes.Private && propertyAccessibility != MemberAttributes.Private)
            { 
                if (isGetter) 
                {
                    fixups.Add(new FixUp(propertyFqName, FixUpType.MarkPropertyGetAsPrivate)); 
                }
                else
                {
                    fixups.Add(new FixUp(propertyFqName, FixUpType.MarkPropertySetAsPrivate)); 
                }
            } 
 
            // Internal
            if (accessibility == MemberAttributes.Assembly && propertyAccessibility != MemberAttributes.Assembly) 
            {
                if (isGetter)
                {
                    fixups.Add(new FixUp(propertyFqName, FixUpType.MarkPropertyGetAsInternal)); 
                }
                else 
                { 
                    fixups.Add(new FixUp(propertyFqName, FixUpType.MarkPropertySetAsInternal));
                } 
            }

            // Public
            if (accessibility == MemberAttributes.Public && propertyAccessibility != MemberAttributes.Public) 
            {
                if (isGetter) 
                { 
                    fixups.Add(new FixUp(propertyFqName, FixUpType.MarkPropertyGetAsPublic));
                } 
                else
                {
                    fixups.Add(new FixUp(propertyFqName, FixUpType.MarkPropertySetAsPublic));
                } 
            }
 
            // Protected 
            if (accessibility == MemberAttributes.Family && propertyAccessibility != MemberAttributes.Family)
            { 
                if (isGetter)
                {
                    fixups.Add(new FixUp(propertyFqName, FixUpType.MarkPropertyGetAsProtected));
                } 
                else
                { 
                    fixups.Add(new FixUp(propertyFqName, FixUpType.MarkPropertySetAsProtected)); 
                }
            } 
        }

        private CodeExpression GetEnumValue(T value)
        { 
            Type type = typeof(T);
            return new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(TypeReference.ForType(type)), Enum.GetName(type, value)); 
        } 

        ///  
        /// See if a property names will hide a base class member name
        /// 
        private bool HidesBaseClassProperty
        { 
            get
            { 
                StructuralType parentBaseClass = Item.DeclaringType.BaseType as StructuralType; 
                if (parentBaseClass != null && parentBaseClass.Members.Contains(PropertyName))
                    return true; 

                return false;
            }
        } 

        ///  
        /// 
        /// 
        ///  
        /// 
        /// 
        private CodeTypeReference GetType(EdmProperty property, bool getElementType)
        { 
            PropertyTypeReferences types = default(PropertyTypeReferences);
            EdmType propertyType = property.TypeUsage.EdmType; 
 
            // Initialize types
            if (Helper.IsPrimitiveType(propertyType)) 
            {
                types = new PropertyTypeReferences(TypeReference, (PrimitiveType)propertyType);
            }
            else if (Helper.IsComplexType(propertyType)) 
            {
                types = new PropertyTypeReferences(TypeReference, (ComplexType)propertyType, Generator); 
            } 
            else if (Helper.IsCollectionType(propertyType))
            { 
                TypeUsage typeUsage = ((CollectionType)propertyType).TypeUsage;
                if (Helper.IsPrimitiveType(typeUsage.EdmType))
                {
                    types = new PropertyTypeReferences(TypeReference, (PrimitiveType)typeUsage.EdmType, GetCollectionKind(property.TypeUsage)); 
                }
                else 
                { 
                    Debug.Assert(Helper.IsComplexType(typeUsage.EdmType));
                    types = new PropertyTypeReferences(TypeReference, (ComplexType)typeUsage.EdmType, GetCollectionKind(property.TypeUsage), Generator); 
                }
            }
            else
            { 
                // shouldn't be able to get here....
                Debug.Fail("Unexpected Property.Type type: " + propertyType.GetType()); 
            } 

            // Set types, or retrieve existing types if they have been set in the interim 
            // Don't cache Collection types since CollectionKind is really a facet and
            //it is not part of the key we are using for the dictionary used to cache.
            if (!Helper.IsCollectionType(propertyType))
            { 
                Debug.Assert(types.NonNullable != null && types.Nullable != null, "did you forget to set the types variable?");
            } 
 
            if (property.Nullable)
            { 
                return types.Nullable;
            }
            else
            { 
                return types.NonNullable;
            } 
        } 

 
        private static CollectionKind GetCollectionKind(TypeUsage usage)
        {
            Facet collectionFacet;
            if (usage.Facets.TryGetValue(EdmConstants.CollectionKind, false, out collectionFacet)) 
            {
                return (CollectionKind)collectionFacet.Value; 
            } 

            return CollectionKind.None; 
        }

        private string OnChangingPartialMethodName(string propertyName) { return "On" + propertyName + "Changing"; }
        private string OnChangedPartialMethodName(string propertyName) { return "On" + propertyName + "Changed"; } 

        #endregion 
 
        #region Private Properties
        ///  
        ///
        /// 
        private CodeFieldReferenceExpression FieldRef
        { 
            get
            { 
                if (_fieldRef == null) 
                    _fieldRef = new CodeFieldReferenceExpression(ThisRef, FieldName);
 
                return _fieldRef;
            }
        }
        ///  
        ///
        ///  
        private CodeFieldReferenceExpression ComplexPropertyInitializedFieldRef 
        {
            get 
            {
                if (_complexPropertyInitializedFieldRef == null)
                    _complexPropertyInitializedFieldRef = new CodeFieldReferenceExpression(ThisRef, ComplexPropertyInitializedFieldName);
 
                return _complexPropertyInitializedFieldRef;
            } 
        } 

        ///  
        ///
        /// 
        private string FieldName
        { 
            get
            { 
                return Utils.FieldNameFromPropName(PropertyName); 
            }
        } 
        /// 
        ///
        /// 
        private string ComplexPropertyInitializedFieldName 
        {
            get 
            { 
                return Utils.ComplexPropertyInitializedNameFromPropName(PropertyName);
            } 
        }

        /// 
        /// 
        /// 
        internal static bool HasDefault(EdmProperty property) 
        { 
            return property.DefaultValue != null;
        } 

        /// 
        ///
        ///  
        private CodeExpression GetDefaultValueExpression(EdmProperty property)
        { 
            PrimitiveTypeKind type; 
            object value = property.DefaultValue;
            if (value != null 
                 && Utils.TryGetPrimitiveTypeKind(property.TypeUsage.EdmType, out type))
            {
                switch (type)
                { 
                    case PrimitiveTypeKind.Boolean:
                    case PrimitiveTypeKind.Byte: 
                    case PrimitiveTypeKind.Int16: 
                    case PrimitiveTypeKind.Int32:
                    case PrimitiveTypeKind.Int64: 
                    case PrimitiveTypeKind.Decimal:
                    case PrimitiveTypeKind.Single:
                    case PrimitiveTypeKind.Double:
                    case PrimitiveTypeKind.String: 
                        {
                            if (!property.Nullable && value.Equals(TypeSystem.GetDefaultValue(value.GetType()))) 
                            { 
                                break;
                            } 
                            return new CodePrimitiveExpression(value);
                        }
                    case PrimitiveTypeKind.Guid:
                        { 
                            if (!property.Nullable && value.Equals(TypeSystem.GetDefaultValue(value.GetType())))
                            { 
                                break; 
                            }
                            return GetCodeExpressionFromGuid(value); 
                        }
                    case PrimitiveTypeKind.DateTime:
                        {
                            if (!property.Nullable && value.Equals(TypeSystem.GetDefaultValue(value.GetType()))) 
                            {
                                break; 
                            } 
                            return GetCodeExpressionFromDateTimeDefaultValue(value, property);
                        } 
                    case PrimitiveTypeKind.Binary:
                        {
                            return GetCodeExpressionFromBinary(value);
                        } 
                }
                return null; 
            } 

            return null; 
        }

        /// 
        /// 
        /// 
        private CodeExpression GetCodeExpressionFromBinary(object value) 
        { 
            byte[] data = (byte[])value;
            CodeExpression[] bytes = new CodeExpression[data.Length]; 

            for (int iByte = 0; iByte < data.Length; ++iByte)
            {
                bytes[iByte] = new CodePrimitiveExpression(data[iByte]); 
            }
 
            return new CodeArrayCreateExpression(TypeReference.ByteArray, bytes); 
        }
 
        /// 
        ///
        /// 
        ///  
        private CodeExpression GetCodeExpressionFromGuid(object value)
        { 
            Guid guid = (Guid)value; 
            return new CodeObjectCreateExpression(TypeReference.Guid,
                new CodePrimitiveExpression(guid.ToString("D", CultureInfo.InvariantCulture))); 
        }

        /// 
        /// 
        /// 
        private CodeExpression GetCodeExpressionFromDateTimeDefaultValue(object value, EdmProperty property) 
        { 
            DateTime utc = (DateTime)value;
            DateTime dateTime = DateTime.SpecifyKind(utc, DateTimeKind.Unspecified); 

            return new CodeObjectCreateExpression(TypeReference.DateTime, new CodePrimitiveExpression(dateTime.Ticks), GetEnumValue(DateTimeKind.Unspecified));
        }
 
        /// 
        /// 
        ///  
        public bool IsVirtualProperty
        { 
            get
            {
                return false;
            } 
        }
 
        private struct PropertyTypeReferences 
        {
            CodeTypeReference _nonNullable; 
            CodeTypeReference _nullable;
            public PropertyTypeReferences(TypeReference typeReference, PrimitiveType primitiveType)
                : this(typeReference, primitiveType, CollectionKind.None)
            { 
            }
 
            public PropertyTypeReferences(TypeReference typeReference, PrimitiveType primitiveType, CollectionKind collectionKind) 
            {
                Type type = primitiveType.ClrEquivalentType; 
                if (collectionKind == CollectionKind.None)
                {
                    _nonNullable = typeReference.ForType(type);
                    if (type.IsValueType) 
                    {
                        _nullable = typeReference.NullableForType(type); 
                    } 
                    else
                    { 
                        _nullable = typeReference.ForType(type);
                    }
                }
                else 
                {
                    CodeTypeReference primitiveTypeRef = typeReference.ForType(type); 
                    CodeTypeReference collectionType = GetCollectionTypeReference(typeReference, primitiveTypeRef, collectionKind); 
                    _nonNullable = collectionType;
                    _nullable = collectionType; 
                }
            }

            public PropertyTypeReferences(TypeReference typeReference, ComplexType complexType, CollectionKind collectionKind, ClientApiGenerator generator) 
            {
                CodeTypeReference baseType = generator.GetLeastPossibleQualifiedTypeReference(complexType); 
                baseType = GetCollectionTypeReference(typeReference, baseType, collectionKind); 
                _nonNullable = baseType;
                _nullable = baseType; 
            }

            private static CodeTypeReference GetCollectionTypeReference(TypeReference typeReference, CodeTypeReference baseType, CollectionKind collectionKind)
            { 
                if (collectionKind == CollectionKind.Bag)
                { 
                    baseType = GetCollectionTypeReferenceForBagSemantics(typeReference, baseType); 
                }
                else if (collectionKind == CollectionKind.List) 
                {
                    baseType = GetCollectionTypeReferenceForListSemantics(typeReference, baseType);
                }
                else 
                {
                    Debug.Assert(collectionKind == CollectionKind.None, "Was another CollectionKind value added"); 
                    // nothing more to do for .None 
                }
                return baseType; 
            }

            public PropertyTypeReferences(TypeReference typeReference, ComplexType complexType, ClientApiGenerator generator)
                : this(typeReference, complexType, CollectionKind.None, generator) 
            {
            } 
 
            private static CodeTypeReference GetCollectionTypeReferenceForBagSemantics(TypeReference typeReference, CodeTypeReference baseType)
            { 
                CodeTypeReference typeRef = typeReference.ForType(typeof(System.Collections.Generic.ICollection<>), baseType);
                return typeRef;
            }
 
            private static CodeTypeReference GetCollectionTypeReferenceForListSemantics(TypeReference typeReference, CodeTypeReference baseType)
            { 
                CodeTypeReference typeRef = typeReference.ForType(typeof(System.Collections.Generic.IList<>), baseType); 
                return typeRef;
            } 

            public CodeTypeReference NonNullable
            {
                get { return _nonNullable; } 
            }
            public CodeTypeReference Nullable 
            { 
                get { return _nullable; }
            } 
        }
        #endregion

 

        // properties from ClassPropertyEmitter 
 
        public string PropertyFQName
        { 
            get
            {
                return Item.DeclaringType.FullName + "." + Item.Name;
            } 
        }
 
        public string PropertyName 
        {
            get 
            {
                return EntityPropertyName;
            }
        } 

        private string PropertyClassName 
        { 
            get
            { 
                return Item.DeclaringType.Name;
            }
        }
 
        private CodeMemberProperty EmitPropertyDeclaration(MemberAttributes scope, CodeTypeReference propertyType, bool isVirtual,
            bool hidesBaseProperty) 
        { 
            Debug.Assert(GetAccessibilityRank(scope) >= 0, "scope should only be an accessibility attribute");
 
            CodeMemberProperty memberProperty = new CodeMemberProperty();
            memberProperty.Name = PropertyName;
            CommentEmitter.EmitSummaryComments(Item, memberProperty.Comments);
 
            memberProperty.Attributes = scope;
 
            if (!isVirtual) 
            {
                memberProperty.Attributes |= MemberAttributes.Final; 
            }

            if (hidesBaseProperty || AncestorClassDefinesName(memberProperty.Name))
            { 
                memberProperty.Attributes |= MemberAttributes.New;
            } 
 
            memberProperty.Type = propertyType;
 
            return memberProperty;
        }

        private void DisallowReturnTypeChange(CodeTypeReference baseType, CodeTypeReference newType) 
        {
            if (Helper.IsCollectionType(Item.TypeUsage.EdmType) && GetCollectionKind(Item.TypeUsage) != CollectionKind.None) 
            { 
                if (newType == null)
                { 
                    throw EDesignUtil.InvalidOperation(Strings.CannotChangePropertyReturnTypeToNull(Item.Name, Item.DeclaringType.Name));
                }

                // you can change the return type of collection properties 
                // we don't even need to check
                return; 
            } 

 
            if (!(baseType == null && newType == null) &&
                (
                    (baseType != null && !baseType.Equals(newType)) ||
                    (newType != null && !newType.Equals(baseType)) 
                )
               ) 
            { 
                throw EDesignUtil.InvalidOperation(Strings.CannotChangePropertyReturnType(Item.Name, Item.DeclaringType.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