EntityContainerEmitter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Design / system / Data / EntityModel / Emitters / EntityContainerEmitter.cs / 1305376 / EntityContainerEmitter.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.Linq; 
 
namespace System.Data.EntityModel.Emitters
{ 
    /// 
    /// This class is responsible for emiting the code for the EntityContainer schema element
    /// 
    internal sealed class EntityContainerEmitter : SchemaTypeEmitter 
    {
        #region Fields 
 
        private const string _onContextCreatedString = "OnContextCreated";
 
        #endregion

        #region Constructors
 
        /// 
        /// 
        ///  
        /// 
        ///  
        public EntityContainerEmitter(ClientApiGenerator generator, EntityContainer entityContainer)
            : base(generator, entityContainer)
        {
        } 

        #endregion 
 
        #region Properties, Methods, Events & Delegates
        ///  
        /// Creates the CodeTypeDeclarations necessary to generate the code for the EntityContainer schema element
        /// 
        /// 
        public override CodeTypeDeclarationCollection EmitApiClass() 
        {
            Validate(); // emitter-specific validation 
 
            // declare the new class
            // public partial class LOBScenario : ObjectContext 
            CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(Item.Name);
            typeDecl.IsPartial = true;

            // raise the TypeGenerated event 
            CodeTypeReference objectContextTypeRef = TypeReference.ObjectContext;
            TypeGeneratedEventArgs eventArgs = new TypeGeneratedEventArgs(Item, objectContextTypeRef); 
            Generator.RaiseTypeGeneratedEvent(eventArgs); 

            if (eventArgs.BaseType != null && !eventArgs.BaseType.Equals(objectContextTypeRef)) 
            {
                typeDecl.BaseTypes.Add(eventArgs.BaseType);
            }
            else 
            {
                typeDecl.BaseTypes.Add(TypeReference.ObjectContext); 
            } 

            AddInterfaces(Item.Name, typeDecl, eventArgs.AdditionalInterfaces); 

            CommentEmitter.EmitSummaryComments(Item, typeDecl.Comments);
            EmitTypeAttributes(Item.Name, typeDecl, eventArgs.AdditionalAttributes);
 
            bool needTypeMapper = (0 < this.Generator.NamespaceMap.Count);
 
            var q = from a in this.Generator.EdmItemCollection.GetItems() 
                    where (a.BaseType != null) &&
                          (a.BuiltInTypeKind == BuiltInTypeKind.ComplexType || a.BuiltInTypeKind == BuiltInTypeKind.EntityType) 
                    select a;
            bool hasInheritance = (null != q.FirstOrDefault());

            CreateConstructors(typeDecl, needTypeMapper, hasInheritance); 
            // adding partial OnContextCreated method
            CreateContextPartialMethods(typeDecl); 
 
            if (needTypeMapper || hasInheritance)
            { 
                CreateTypeMappingMethods(typeDecl, needTypeMapper, hasInheritance);
            }

            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets) 
            {
                if (Helper.IsEntitySet(entitySetBase)) 
                { 
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberProperty codeProperty = CreateEntitySetProperty(set); 
                    typeDecl.Members.Add(codeProperty);

                    CodeMemberField codeField = CreateEntitySetField(set);
                    typeDecl.Members.Add(codeField); 
                }
            } 
 
            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets)
            { 
                if (Helper.IsEntitySet(entitySetBase))
                {
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberMethod codeProperty = CreateEntitySetAddObjectMethod(set); 
                    typeDecl.Members.Add(codeProperty);
                } 
            } 

            // additional members, if provided by the event subscriber 
            AddMembers(Item.Name, typeDecl, eventArgs.AdditionalMembers);

            CodeTypeDeclarationCollection typeDecls = new CodeTypeDeclarationCollection();
            typeDecls.Add(typeDecl); 
            return typeDecls;
        } 
 
        /// 
        /// Emitter-specific validation: check if there exist entity containers and 
        /// entity sets that have the same name but differ in case
        /// 
        protected override void Validate()
        { 
            base.Validate();
            Generator.VerifyLanguageCaseSensitiveCompatibilityForEntitySet(Item); 
            VerifyEntityTypeAndSetAccessibilityCompatability(); 
        }
 
        /// 
        /// Verify that Entity Set and Type have compatible accessibilty.
        /// They are compatible if the generated code will compile.
        ///  
        private void VerifyEntityTypeAndSetAccessibilityCompatability()
        { 
            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets) 
            {
                if (Helper.IsEntitySet(entitySetBase)) 
                {
                    EntitySet set = (EntitySet)entitySetBase;
                    if (!AreTypeAndSetAccessCompatible(GetEntityTypeAccessibility(set.ElementType), GetEntitySetPropertyAccessibility(set)))
                    { 
                        Generator.AddError(
                            Strings.EntityTypeAndSetAccessibilityConflict( 
                                set.ElementType.Name, GetAccessibilityCsdlStringFromMemberAttribute(GetEntityTypeAccessibility(set.ElementType)), set.Name, GetAccessibilityCsdlStringFromMemberAttribute(GetEntitySetPropertyAccessibility(set))), 
                            ModelBuilderErrorCode.EntityTypeAndSetAccessibilityConflict,
                            EdmSchemaErrorSeverity.Error); 
                    }
                }
            }
        } 

 
        ///  
        /// Tells whether Entity Type's specified accessibility and Entity Set Property's specified Accessibility will work together (compile) when codegen'd.
        /// False if (Type is internal and Set's Property is Public OR, type is internal and Set's property is protected). 
        /// True otherwise
        /// 
        private bool AreTypeAndSetAccessCompatible(MemberAttributes typeAccess, MemberAttributes setAccess)
        { 
            return !(typeAccess == MemberAttributes.Assembly && (setAccess == MemberAttributes.Public || setAccess == MemberAttributes.Family));
        } 
 
        /// 
        /// Creates the necessary constructors for the entity container. 
        /// 
        private void CreateConstructors(CodeTypeDeclaration typeDecl, bool setupTypeMapper, bool hasInheritance)
        {
            // Constructor that takes a uri 
            //
            // public ctor(System.Uri serviceRoot) 
            //    : base(serviceRoot) 
            // {
            //      this.OnContextCreated(); 
            // }
            CodeConstructor connectionWorkspaceCtor = new CodeConstructor();
            connectionWorkspaceCtor.Attributes = MemberAttributes.Public;
            CodeParameterDeclarationExpression connectionParam = new CodeParameterDeclarationExpression(TypeReference.FromString("System.Uri", true), "serviceRoot"); 
            connectionWorkspaceCtor.Parameters.Add(connectionParam);
            connectionWorkspaceCtor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression(connectionParam.Name)); 
 
            AttributeEmitter.AddGeneratedCodeAttribute(connectionWorkspaceCtor);
 
            CommentEmitter.EmitSummaryComments(Strings.CtorSummaryComment(Item.Name), connectionWorkspaceCtor.Comments);

            // If we have an externally provided namespage (e.g. from Visual Studio), we need to
            // inject a type-mapper because type names won't match between client and server 
            if (setupTypeMapper || hasInheritance)
            { 
                connectionWorkspaceCtor.Statements.Add( 
                    new CodeAssignStatement(
                        new CodeFieldReferenceExpression(ThisRef, "ResolveName"), 
                        new CodeDelegateCreateExpression(
                            TypeReference.ForType(typeof(Func<,>), TypeReference.ForType(typeof(Type)), TypeReference.ForType(typeof(String))),
                             ThisRef,
                             "ResolveNameFromType" 
                         )
                    ) 
                ); 
            }
 
            if (setupTypeMapper)
            {
                connectionWorkspaceCtor.Statements.Add(
                    new CodeAssignStatement( 
                        new CodeFieldReferenceExpression(ThisRef, "ResolveType"),
                        new CodeDelegateCreateExpression( 
                            TypeReference.ForType(typeof(Func<,>), TypeReference.ForType(typeof(String)), TypeReference.ForType(typeof(Type))), 
                             ThisRef,
                             "ResolveTypeFromName" 
                         )
                    )
                );
            } 

            connectionWorkspaceCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression()); 
 
            typeDecl.Members.Add(connectionWorkspaceCtor);
        } 

        /// 
        /// Adds the OnContextCreated partial method for the entity container.
        ///  
        private void CreateContextPartialMethods(CodeTypeDeclaration typeDecl)
        { 
            CodeMemberMethod onContextCreatedPartialMethod = new CodeMemberMethod(); 
            onContextCreatedPartialMethod.Name = _onContextCreatedString;
            onContextCreatedPartialMethod.ReturnType = new CodeTypeReference(typeof(void)); 
            onContextCreatedPartialMethod.Attributes = MemberAttributes.Abstract | MemberAttributes.Public;
            typeDecl.Members.Add(onContextCreatedPartialMethod);

            Generator.FixUps.Add(new FixUp(Item.Name + "." + _onContextCreatedString, FixUpType.MarkAbstractMethodAsPartial)); 
        }
 
        private void CreateTypeMappingMethods(CodeTypeDeclaration typeDecl, bool needTypeMapper, bool hasInheritance) 
        {
            // Special case to compensate for VB's "root namespace" feature. 
            if (this.Generator.Language == LanguageOption.GenerateVBCode)
            {
                AddRootNamespaceField(typeDecl);
            } 

            CodeExpression comparisonExpression = new CodePropertyReferenceExpression( 
                    new CodeTypeReferenceExpression(TypeReference.ForType(typeof(StringComparison))), 
                    Enum.GetName(typeof(StringComparison), this.Generator.LanguageAppropriateStringComparer));
 
            if (needTypeMapper)
            {
                CodeMemberMethod resolveTypeFromName = new CodeMemberMethod();
                resolveTypeFromName.Name = "ResolveTypeFromName"; 
                resolveTypeFromName.Attributes = MemberAttributes.Final | MemberAttributes.Family;
                resolveTypeFromName.Parameters.Add(new CodeParameterDeclarationExpression(TypeReference.ForType(typeof(string)), "typeName")); 
                resolveTypeFromName.ReturnType = TypeReference.ForType(typeof(Type)); 
                AttributeEmitter.AddGeneratedCodeAttribute(resolveTypeFromName);
                CommentEmitter.EmitSummaryComments(Strings.TypeMapperDescription, resolveTypeFromName.Comments); 

                // NOTE: since multiple namespaces can have the same prefix and match the namespace
                // prefix condition, it's important that the prefix check is done is prefix-length
                // order, starting with the longest prefix. 
                var pairs = this.Generator.NamespaceMap.OrderByDescending(p => p.Key.Length).ThenBy(p => p.Key);
 
                foreach (var pair in pairs) 
                {
                    // Assuming pair.Key is "abc" and pair.Value is "def" and len(def)=3, generate: 
                    // if (typeName.StartsWith("abc", StringComparison.Ordinal))
                    //     return this.GetType().Assembly.GetType(string.Concat("def", typeName.Substring(3)), false)
                    // DEVNOTE([....]): we should use GetType(xxx, FALSE) here so it will not throw and fall back to null
                    // GetType(type, bool throw, bool ignoreCase) does not exist in SL, do not use! 
                    resolveTypeFromName.Statements.Add(
                        new CodeConditionStatement( 
                            new CodeMethodInvokeExpression( 
                                new CodeVariableReferenceExpression("typeName"),
                                "StartsWith", 
                                new CodePrimitiveExpression(pair.Key),
                                comparisonExpression
                            ),
                            new CodeMethodReturnStatement( 
                                new CodeMethodInvokeExpression(
                                    new CodePropertyReferenceExpression( 
                                        new CodeMethodInvokeExpression( 
                                            ThisRef,
                                            "GetType" 
                                        ),
                                        "Assembly"
                                    ),
                                    "GetType", 
                                    new CodeMethodInvokeExpression(
                                        new CodeTypeReferenceExpression(TypeReference.ForType(typeof(string))), 
                                        "Concat", 
                                        this.LanguageSpecificNamespace(pair.Value),
                                        new CodeMethodInvokeExpression( 
                                            new CodeVariableReferenceExpression("typeName"),
                                            "Substring",
                                            new CodePrimitiveExpression(pair.Key.Length)
                                        ) 
                                    ),
                                    new CodePrimitiveExpression(false) 
                                ) 
                            )
                        ) 
                    );
                }

                resolveTypeFromName.Statements.Add( 
                    new CodeMethodReturnStatement(
                        new CodePrimitiveExpression(null))); 
 
                typeDecl.Members.Add(resolveTypeFromName);
            } 

            CodeMemberMethod resolveNameFromType = new CodeMemberMethod();
            resolveNameFromType.Name = "ResolveNameFromType";
            resolveNameFromType.Attributes = MemberAttributes.Final | MemberAttributes.Family; 
            resolveNameFromType.Parameters.Add(new CodeParameterDeclarationExpression(TypeReference.ForType(typeof(Type)), "clientType"));
            resolveNameFromType.ReturnType = TypeReference.ForType(typeof(String)); 
            AttributeEmitter.AddGeneratedCodeAttribute(resolveNameFromType); 
            CommentEmitter.EmitSummaryComments(Strings.TypeMapperDescription, resolveNameFromType.Comments);
 
            // NOTE: in this case order also matters, but the length of the CLR
            // namespace is what needs to be considered.
            var reversePairs = Generator.NamespaceMap.OrderByDescending(p => p.Value.Length).ThenBy(p => p.Key);
 
            foreach (var pair in reversePairs)
            { 
                // Assuming pair.Key is "abc" and pair.Value is "def", generate: 
                // if (t.Namespace.Equals("def", StringComparison.Ordinal)) return string.Concat("abc.", t.Name);
 
                resolveNameFromType.Statements.Add(
                    new CodeConditionStatement(
                        new CodeMethodInvokeExpression(
                            new CodePropertyReferenceExpression( 
                                new CodeVariableReferenceExpression("clientType"),
                                "Namespace" 
                            ), 
                            "Equals",
                            this.LanguageSpecificNamespace(pair.Value), 
                            comparisonExpression
                        ),
                        new CodeMethodReturnStatement(
                            new CodeMethodInvokeExpression( 
                                new CodeTypeReferenceExpression(TypeReference.ForType(typeof(string))),
                                "Concat", 
                                new CodePrimitiveExpression(pair.Key + "."), 
                                new CodePropertyReferenceExpression(
                                    new CodeVariableReferenceExpression("clientType"), 
                                    "Name"
                                )
                            )
                        ) 
                    )
                ); 
            } 

            if (hasInheritance) 
            {
                CodeExpression clientTypeFullName = new CodePropertyReferenceExpression(
                                                        new CodeVariableReferenceExpression("clientType"),
                                                        "FullName"); 

                if (this.Generator.Language == LanguageOption.GenerateVBCode) 
                { 
                    // return clientType.FullName.Substring(ROOTNAMESPACE.Length);
                    resolveNameFromType.Statements.Add( 
                        new CodeMethodReturnStatement(
                            new CodeMethodInvokeExpression(
                                clientTypeFullName,
                                "Substring", 
                                new CodePropertyReferenceExpression(
                                    new CodeVariableReferenceExpression("ROOTNAMESPACE"), 
                                    "Length" 
                                )
                            ) 
                        )
                    );
                }
                else 
                {
                    // return clientType.FullName; 
                    resolveNameFromType.Statements.Add(new CodeMethodReturnStatement(clientTypeFullName)); 
                }
            } 
            else
            {
                resolveNameFromType.Statements.Add(
                    new CodeMethodReturnStatement( 
                        NullExpression
                    ) 
                ); 
            }
 
            typeDecl.Members.Add(resolveNameFromType);
        }

        private void AddRootNamespaceField(CodeTypeDeclaration typeDecl) 
        {
            // Add this field (VB declaration), where known client type name is ClientNS.BikesEntities 
            // ROOTNAMESPACE = GetType(ClientNS.BikesEntities).Namespace.Remove(GetType(ClientNS.BikesEntities).Namespace.LastIndexOf("ClientNS")) 

            EntityContainer container = (EntityContainer)this.Item; 
            string containerNamespace = Generator.GetClientTypeNamespace(this.Generator.GetContainerNamespace(container));
            // VB-ism: if namespace and type names are the same (Blah.Blah), GetType(Blah.Blah) fails...
            string vbScopedcontainerName = (string.IsNullOrEmpty(containerNamespace) || container.Name.Equals(containerNamespace, StringComparison.OrdinalIgnoreCase))
                                           ? container.Name : (containerNamespace + "." + container.Name); 

 
            CodeExpression namespaceAccess = new CodePropertyReferenceExpression( 
                                                new CodeTypeOfExpression(vbScopedcontainerName),
                                                "Namespace"); 

            CodeMemberField rootNamespaceField = new CodeMemberField(
                                                    TypeReference.ForType(typeof(string)),
                                                    "ROOTNAMESPACE"); 
            rootNamespaceField.Attributes = MemberAttributes.Static | MemberAttributes.Private;
            rootNamespaceField.InitExpression = new CodeMethodInvokeExpression( 
                                                    namespaceAccess, 
                                                    "Remove",
                                                    new CodeMethodInvokeExpression( 
                                                        namespaceAccess,
                                                        "LastIndexOf",
                                                        new CodePrimitiveExpression(containerNamespace)));
            AttributeEmitter.AddGeneratedCodeAttribute(rootNamespaceField); 
            typeDecl.Members.Add(rootNamespaceField);
        } 
 
        private CodeExpression LanguageSpecificNamespace(string ns)
        { 
            if (this.Generator.Language == LanguageOption.GenerateVBCode)
            {
                return new CodeMethodInvokeExpression(
                    new CodeTypeReferenceExpression(TypeReference.ForType(typeof(string))), 
                    "Concat",
                    new CodeVariableReferenceExpression("ROOTNAMESPACE"), 
                    new CodePrimitiveExpression(ns)); 
            }
            else 
            {
                return new CodePrimitiveExpression(ns);
            }
        } 

        private CodeMemberField CreateEntitySetField(EntitySet set) 
        { 
            Debug.Assert(set != null, "Field is Null");
 
            // trying to get
            //
            // private ObjectQuery _Customers = null;
 
            CodeMemberField codeField = new CodeMemberField();
            codeField.Attributes = MemberAttributes.Final | MemberAttributes.Private; 
            codeField.Name = Utils.FieldNameFromPropName(set.Name); 
            AttributeEmitter.AddGeneratedCodeAttribute(codeField);
 
            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);
            codeField.Type = TypeReference.AdoFrameworkGenericClass("DataServiceQuery", genericParameter);
            return codeField;
        } 

        private CodeMemberProperty CreateEntitySetProperty(EntitySet set) 
        { 
            Debug.Assert(set != null, "Property is Null");
 
            // trying to get
            //
            // [System.ComponentModel.Browsable(false)]
            // public ObjectQuery Customers 
            // {
            //      get 
            //      { 
            //          if ((this._Customers == null))
            //          { 
            //              this._Customers = base.CreateQuery("[Customers]");
            //          }
            //          return this._Customers;
            //      } 
            // }
            CodeMemberProperty codeProperty = new CodeMemberProperty(); 
            codeProperty.Attributes = MemberAttributes.Final | GetEntitySetPropertyAccessibility(set); 
            codeProperty.Name = set.Name;
            codeProperty.HasGet = true; 
            codeProperty.HasSet = false;

            // SQLBUDT 598300: property to get query hides a property on base Context?
            if (null != TypeReference.ObjectContextBaseClassType.GetProperty(set.Name)) 
            {
                codeProperty.Attributes |= MemberAttributes.New; 
            } 

            AttributeEmitter.AddBrowsableAttribute(codeProperty); 
            AttributeEmitter.AddGeneratedCodeAttribute(codeProperty);

            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);
            codeProperty.Type = TypeReference.AdoFrameworkGenericClass("DataServiceQuery", 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 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 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(), 
                                "CreateQuery",
                                new CodeTypeReference[] { genericParameter } 
                            ), 
                            new CodePrimitiveExpression(set.Name)
                        ) 
                    )
                )
            );
 
            codeProperty.GetStatements.Add(
                new CodeMethodReturnStatement( 
                    new CodeFieldReferenceExpression( 
                        ThisRef,
                        fieldName 
                    )
                )
            );
 
            // property summary
            CommentEmitter.EmitSummaryComments(set, codeProperty.Comments); 
 
            return codeProperty;
        } 

        /// 
        /// Create an AddTo-EntitysetName methiod for each entityset in the context.
        ///  
        /// EntityContainerEntitySet that we will go over to get the existing entitysets.
        ///  Method definition  
 
        private CodeMemberMethod CreateEntitySetAddObjectMethod(EntitySet set)
        { 
            Debug.Assert(set != null, "Property is Null");

            // trying to get
            // 
            // public void AddToCustomer(Customer customer)
            // { 
            //      base.AddObject("Customer", customer); 
            // }
            CodeMemberMethod codeMethod = new CodeMemberMethod(); 
            codeMethod.Attributes = MemberAttributes.Final | GetEntityTypeAccessibility(set.ElementType);
            codeMethod.Name = ("AddTo" + set.Name);

            CodeParameterDeclarationExpression parameter = new CodeParameterDeclarationExpression(); 

            parameter.Type = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType); 
            parameter.Name = Utils.CamelCase(set.ElementType.Name); 
            parameter.Name = Utils.SetSpecialCaseForFxCopOnPropertyName(parameter.Name);
            codeMethod.Parameters.Add(parameter); 

            codeMethod.ReturnType = new CodeTypeReference(typeof(void));

            AttributeEmitter.AddGeneratedCodeAttribute(codeMethod); 

            codeMethod.Statements.Add( 
                new CodeMethodInvokeExpression( 
                    new CodeBaseReferenceExpression(),
                    "AddObject", 
                    new CodePrimitiveExpression(set.Name),
                    new CodeFieldReferenceExpression(null, parameter.Name)
                )
            ); 

            // method summary 
            CommentEmitter.EmitSummaryComments(set, codeMethod.Comments); 
            return codeMethod;
        } 

        /// 
        /// return a code expression for invoking OnContextCreated partial method
        ///  
        private CodeMethodInvokeExpression OnContextCreatedCodeMethodInvokeExpression()
        { 
            return (new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), _onContextCreatedString, new CodeExpression[] { })); 
        }
 
        /// 
        /// Returns the type specific SchemaElement
        /// 
        private new EntityContainer Item 
        {
            get 
            { 
                return base.Item as EntityContainer;
            } 
        }

        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.CodeDom; 
using System.Collections.Generic;
using System.Data.Metadata.Edm;
using System.Data.Services.Design;
using System.Data.Services.Design.Common; 
using System.Diagnostics;
using System.Linq; 
 
namespace System.Data.EntityModel.Emitters
{ 
    /// 
    /// This class is responsible for emiting the code for the EntityContainer schema element
    /// 
    internal sealed class EntityContainerEmitter : SchemaTypeEmitter 
    {
        #region Fields 
 
        private const string _onContextCreatedString = "OnContextCreated";
 
        #endregion

        #region Constructors
 
        /// 
        /// 
        ///  
        /// 
        ///  
        public EntityContainerEmitter(ClientApiGenerator generator, EntityContainer entityContainer)
            : base(generator, entityContainer)
        {
        } 

        #endregion 
 
        #region Properties, Methods, Events & Delegates
        ///  
        /// Creates the CodeTypeDeclarations necessary to generate the code for the EntityContainer schema element
        /// 
        /// 
        public override CodeTypeDeclarationCollection EmitApiClass() 
        {
            Validate(); // emitter-specific validation 
 
            // declare the new class
            // public partial class LOBScenario : ObjectContext 
            CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(Item.Name);
            typeDecl.IsPartial = true;

            // raise the TypeGenerated event 
            CodeTypeReference objectContextTypeRef = TypeReference.ObjectContext;
            TypeGeneratedEventArgs eventArgs = new TypeGeneratedEventArgs(Item, objectContextTypeRef); 
            Generator.RaiseTypeGeneratedEvent(eventArgs); 

            if (eventArgs.BaseType != null && !eventArgs.BaseType.Equals(objectContextTypeRef)) 
            {
                typeDecl.BaseTypes.Add(eventArgs.BaseType);
            }
            else 
            {
                typeDecl.BaseTypes.Add(TypeReference.ObjectContext); 
            } 

            AddInterfaces(Item.Name, typeDecl, eventArgs.AdditionalInterfaces); 

            CommentEmitter.EmitSummaryComments(Item, typeDecl.Comments);
            EmitTypeAttributes(Item.Name, typeDecl, eventArgs.AdditionalAttributes);
 
            bool needTypeMapper = (0 < this.Generator.NamespaceMap.Count);
 
            var q = from a in this.Generator.EdmItemCollection.GetItems() 
                    where (a.BaseType != null) &&
                          (a.BuiltInTypeKind == BuiltInTypeKind.ComplexType || a.BuiltInTypeKind == BuiltInTypeKind.EntityType) 
                    select a;
            bool hasInheritance = (null != q.FirstOrDefault());

            CreateConstructors(typeDecl, needTypeMapper, hasInheritance); 
            // adding partial OnContextCreated method
            CreateContextPartialMethods(typeDecl); 
 
            if (needTypeMapper || hasInheritance)
            { 
                CreateTypeMappingMethods(typeDecl, needTypeMapper, hasInheritance);
            }

            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets) 
            {
                if (Helper.IsEntitySet(entitySetBase)) 
                { 
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberProperty codeProperty = CreateEntitySetProperty(set); 
                    typeDecl.Members.Add(codeProperty);

                    CodeMemberField codeField = CreateEntitySetField(set);
                    typeDecl.Members.Add(codeField); 
                }
            } 
 
            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets)
            { 
                if (Helper.IsEntitySet(entitySetBase))
                {
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberMethod codeProperty = CreateEntitySetAddObjectMethod(set); 
                    typeDecl.Members.Add(codeProperty);
                } 
            } 

            // additional members, if provided by the event subscriber 
            AddMembers(Item.Name, typeDecl, eventArgs.AdditionalMembers);

            CodeTypeDeclarationCollection typeDecls = new CodeTypeDeclarationCollection();
            typeDecls.Add(typeDecl); 
            return typeDecls;
        } 
 
        /// 
        /// Emitter-specific validation: check if there exist entity containers and 
        /// entity sets that have the same name but differ in case
        /// 
        protected override void Validate()
        { 
            base.Validate();
            Generator.VerifyLanguageCaseSensitiveCompatibilityForEntitySet(Item); 
            VerifyEntityTypeAndSetAccessibilityCompatability(); 
        }
 
        /// 
        /// Verify that Entity Set and Type have compatible accessibilty.
        /// They are compatible if the generated code will compile.
        ///  
        private void VerifyEntityTypeAndSetAccessibilityCompatability()
        { 
            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets) 
            {
                if (Helper.IsEntitySet(entitySetBase)) 
                {
                    EntitySet set = (EntitySet)entitySetBase;
                    if (!AreTypeAndSetAccessCompatible(GetEntityTypeAccessibility(set.ElementType), GetEntitySetPropertyAccessibility(set)))
                    { 
                        Generator.AddError(
                            Strings.EntityTypeAndSetAccessibilityConflict( 
                                set.ElementType.Name, GetAccessibilityCsdlStringFromMemberAttribute(GetEntityTypeAccessibility(set.ElementType)), set.Name, GetAccessibilityCsdlStringFromMemberAttribute(GetEntitySetPropertyAccessibility(set))), 
                            ModelBuilderErrorCode.EntityTypeAndSetAccessibilityConflict,
                            EdmSchemaErrorSeverity.Error); 
                    }
                }
            }
        } 

 
        ///  
        /// Tells whether Entity Type's specified accessibility and Entity Set Property's specified Accessibility will work together (compile) when codegen'd.
        /// False if (Type is internal and Set's Property is Public OR, type is internal and Set's property is protected). 
        /// True otherwise
        /// 
        private bool AreTypeAndSetAccessCompatible(MemberAttributes typeAccess, MemberAttributes setAccess)
        { 
            return !(typeAccess == MemberAttributes.Assembly && (setAccess == MemberAttributes.Public || setAccess == MemberAttributes.Family));
        } 
 
        /// 
        /// Creates the necessary constructors for the entity container. 
        /// 
        private void CreateConstructors(CodeTypeDeclaration typeDecl, bool setupTypeMapper, bool hasInheritance)
        {
            // Constructor that takes a uri 
            //
            // public ctor(System.Uri serviceRoot) 
            //    : base(serviceRoot) 
            // {
            //      this.OnContextCreated(); 
            // }
            CodeConstructor connectionWorkspaceCtor = new CodeConstructor();
            connectionWorkspaceCtor.Attributes = MemberAttributes.Public;
            CodeParameterDeclarationExpression connectionParam = new CodeParameterDeclarationExpression(TypeReference.FromString("System.Uri", true), "serviceRoot"); 
            connectionWorkspaceCtor.Parameters.Add(connectionParam);
            connectionWorkspaceCtor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression(connectionParam.Name)); 
 
            AttributeEmitter.AddGeneratedCodeAttribute(connectionWorkspaceCtor);
 
            CommentEmitter.EmitSummaryComments(Strings.CtorSummaryComment(Item.Name), connectionWorkspaceCtor.Comments);

            // If we have an externally provided namespage (e.g. from Visual Studio), we need to
            // inject a type-mapper because type names won't match between client and server 
            if (setupTypeMapper || hasInheritance)
            { 
                connectionWorkspaceCtor.Statements.Add( 
                    new CodeAssignStatement(
                        new CodeFieldReferenceExpression(ThisRef, "ResolveName"), 
                        new CodeDelegateCreateExpression(
                            TypeReference.ForType(typeof(Func<,>), TypeReference.ForType(typeof(Type)), TypeReference.ForType(typeof(String))),
                             ThisRef,
                             "ResolveNameFromType" 
                         )
                    ) 
                ); 
            }
 
            if (setupTypeMapper)
            {
                connectionWorkspaceCtor.Statements.Add(
                    new CodeAssignStatement( 
                        new CodeFieldReferenceExpression(ThisRef, "ResolveType"),
                        new CodeDelegateCreateExpression( 
                            TypeReference.ForType(typeof(Func<,>), TypeReference.ForType(typeof(String)), TypeReference.ForType(typeof(Type))), 
                             ThisRef,
                             "ResolveTypeFromName" 
                         )
                    )
                );
            } 

            connectionWorkspaceCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression()); 
 
            typeDecl.Members.Add(connectionWorkspaceCtor);
        } 

        /// 
        /// Adds the OnContextCreated partial method for the entity container.
        ///  
        private void CreateContextPartialMethods(CodeTypeDeclaration typeDecl)
        { 
            CodeMemberMethod onContextCreatedPartialMethod = new CodeMemberMethod(); 
            onContextCreatedPartialMethod.Name = _onContextCreatedString;
            onContextCreatedPartialMethod.ReturnType = new CodeTypeReference(typeof(void)); 
            onContextCreatedPartialMethod.Attributes = MemberAttributes.Abstract | MemberAttributes.Public;
            typeDecl.Members.Add(onContextCreatedPartialMethod);

            Generator.FixUps.Add(new FixUp(Item.Name + "." + _onContextCreatedString, FixUpType.MarkAbstractMethodAsPartial)); 
        }
 
        private void CreateTypeMappingMethods(CodeTypeDeclaration typeDecl, bool needTypeMapper, bool hasInheritance) 
        {
            // Special case to compensate for VB's "root namespace" feature. 
            if (this.Generator.Language == LanguageOption.GenerateVBCode)
            {
                AddRootNamespaceField(typeDecl);
            } 

            CodeExpression comparisonExpression = new CodePropertyReferenceExpression( 
                    new CodeTypeReferenceExpression(TypeReference.ForType(typeof(StringComparison))), 
                    Enum.GetName(typeof(StringComparison), this.Generator.LanguageAppropriateStringComparer));
 
            if (needTypeMapper)
            {
                CodeMemberMethod resolveTypeFromName = new CodeMemberMethod();
                resolveTypeFromName.Name = "ResolveTypeFromName"; 
                resolveTypeFromName.Attributes = MemberAttributes.Final | MemberAttributes.Family;
                resolveTypeFromName.Parameters.Add(new CodeParameterDeclarationExpression(TypeReference.ForType(typeof(string)), "typeName")); 
                resolveTypeFromName.ReturnType = TypeReference.ForType(typeof(Type)); 
                AttributeEmitter.AddGeneratedCodeAttribute(resolveTypeFromName);
                CommentEmitter.EmitSummaryComments(Strings.TypeMapperDescription, resolveTypeFromName.Comments); 

                // NOTE: since multiple namespaces can have the same prefix and match the namespace
                // prefix condition, it's important that the prefix check is done is prefix-length
                // order, starting with the longest prefix. 
                var pairs = this.Generator.NamespaceMap.OrderByDescending(p => p.Key.Length).ThenBy(p => p.Key);
 
                foreach (var pair in pairs) 
                {
                    // Assuming pair.Key is "abc" and pair.Value is "def" and len(def)=3, generate: 
                    // if (typeName.StartsWith("abc", StringComparison.Ordinal))
                    //     return this.GetType().Assembly.GetType(string.Concat("def", typeName.Substring(3)), false)
                    // DEVNOTE([....]): we should use GetType(xxx, FALSE) here so it will not throw and fall back to null
                    // GetType(type, bool throw, bool ignoreCase) does not exist in SL, do not use! 
                    resolveTypeFromName.Statements.Add(
                        new CodeConditionStatement( 
                            new CodeMethodInvokeExpression( 
                                new CodeVariableReferenceExpression("typeName"),
                                "StartsWith", 
                                new CodePrimitiveExpression(pair.Key),
                                comparisonExpression
                            ),
                            new CodeMethodReturnStatement( 
                                new CodeMethodInvokeExpression(
                                    new CodePropertyReferenceExpression( 
                                        new CodeMethodInvokeExpression( 
                                            ThisRef,
                                            "GetType" 
                                        ),
                                        "Assembly"
                                    ),
                                    "GetType", 
                                    new CodeMethodInvokeExpression(
                                        new CodeTypeReferenceExpression(TypeReference.ForType(typeof(string))), 
                                        "Concat", 
                                        this.LanguageSpecificNamespace(pair.Value),
                                        new CodeMethodInvokeExpression( 
                                            new CodeVariableReferenceExpression("typeName"),
                                            "Substring",
                                            new CodePrimitiveExpression(pair.Key.Length)
                                        ) 
                                    ),
                                    new CodePrimitiveExpression(false) 
                                ) 
                            )
                        ) 
                    );
                }

                resolveTypeFromName.Statements.Add( 
                    new CodeMethodReturnStatement(
                        new CodePrimitiveExpression(null))); 
 
                typeDecl.Members.Add(resolveTypeFromName);
            } 

            CodeMemberMethod resolveNameFromType = new CodeMemberMethod();
            resolveNameFromType.Name = "ResolveNameFromType";
            resolveNameFromType.Attributes = MemberAttributes.Final | MemberAttributes.Family; 
            resolveNameFromType.Parameters.Add(new CodeParameterDeclarationExpression(TypeReference.ForType(typeof(Type)), "clientType"));
            resolveNameFromType.ReturnType = TypeReference.ForType(typeof(String)); 
            AttributeEmitter.AddGeneratedCodeAttribute(resolveNameFromType); 
            CommentEmitter.EmitSummaryComments(Strings.TypeMapperDescription, resolveNameFromType.Comments);
 
            // NOTE: in this case order also matters, but the length of the CLR
            // namespace is what needs to be considered.
            var reversePairs = Generator.NamespaceMap.OrderByDescending(p => p.Value.Length).ThenBy(p => p.Key);
 
            foreach (var pair in reversePairs)
            { 
                // Assuming pair.Key is "abc" and pair.Value is "def", generate: 
                // if (t.Namespace.Equals("def", StringComparison.Ordinal)) return string.Concat("abc.", t.Name);
 
                resolveNameFromType.Statements.Add(
                    new CodeConditionStatement(
                        new CodeMethodInvokeExpression(
                            new CodePropertyReferenceExpression( 
                                new CodeVariableReferenceExpression("clientType"),
                                "Namespace" 
                            ), 
                            "Equals",
                            this.LanguageSpecificNamespace(pair.Value), 
                            comparisonExpression
                        ),
                        new CodeMethodReturnStatement(
                            new CodeMethodInvokeExpression( 
                                new CodeTypeReferenceExpression(TypeReference.ForType(typeof(string))),
                                "Concat", 
                                new CodePrimitiveExpression(pair.Key + "."), 
                                new CodePropertyReferenceExpression(
                                    new CodeVariableReferenceExpression("clientType"), 
                                    "Name"
                                )
                            )
                        ) 
                    )
                ); 
            } 

            if (hasInheritance) 
            {
                CodeExpression clientTypeFullName = new CodePropertyReferenceExpression(
                                                        new CodeVariableReferenceExpression("clientType"),
                                                        "FullName"); 

                if (this.Generator.Language == LanguageOption.GenerateVBCode) 
                { 
                    // return clientType.FullName.Substring(ROOTNAMESPACE.Length);
                    resolveNameFromType.Statements.Add( 
                        new CodeMethodReturnStatement(
                            new CodeMethodInvokeExpression(
                                clientTypeFullName,
                                "Substring", 
                                new CodePropertyReferenceExpression(
                                    new CodeVariableReferenceExpression("ROOTNAMESPACE"), 
                                    "Length" 
                                )
                            ) 
                        )
                    );
                }
                else 
                {
                    // return clientType.FullName; 
                    resolveNameFromType.Statements.Add(new CodeMethodReturnStatement(clientTypeFullName)); 
                }
            } 
            else
            {
                resolveNameFromType.Statements.Add(
                    new CodeMethodReturnStatement( 
                        NullExpression
                    ) 
                ); 
            }
 
            typeDecl.Members.Add(resolveNameFromType);
        }

        private void AddRootNamespaceField(CodeTypeDeclaration typeDecl) 
        {
            // Add this field (VB declaration), where known client type name is ClientNS.BikesEntities 
            // ROOTNAMESPACE = GetType(ClientNS.BikesEntities).Namespace.Remove(GetType(ClientNS.BikesEntities).Namespace.LastIndexOf("ClientNS")) 

            EntityContainer container = (EntityContainer)this.Item; 
            string containerNamespace = Generator.GetClientTypeNamespace(this.Generator.GetContainerNamespace(container));
            // VB-ism: if namespace and type names are the same (Blah.Blah), GetType(Blah.Blah) fails...
            string vbScopedcontainerName = (string.IsNullOrEmpty(containerNamespace) || container.Name.Equals(containerNamespace, StringComparison.OrdinalIgnoreCase))
                                           ? container.Name : (containerNamespace + "." + container.Name); 

 
            CodeExpression namespaceAccess = new CodePropertyReferenceExpression( 
                                                new CodeTypeOfExpression(vbScopedcontainerName),
                                                "Namespace"); 

            CodeMemberField rootNamespaceField = new CodeMemberField(
                                                    TypeReference.ForType(typeof(string)),
                                                    "ROOTNAMESPACE"); 
            rootNamespaceField.Attributes = MemberAttributes.Static | MemberAttributes.Private;
            rootNamespaceField.InitExpression = new CodeMethodInvokeExpression( 
                                                    namespaceAccess, 
                                                    "Remove",
                                                    new CodeMethodInvokeExpression( 
                                                        namespaceAccess,
                                                        "LastIndexOf",
                                                        new CodePrimitiveExpression(containerNamespace)));
            AttributeEmitter.AddGeneratedCodeAttribute(rootNamespaceField); 
            typeDecl.Members.Add(rootNamespaceField);
        } 
 
        private CodeExpression LanguageSpecificNamespace(string ns)
        { 
            if (this.Generator.Language == LanguageOption.GenerateVBCode)
            {
                return new CodeMethodInvokeExpression(
                    new CodeTypeReferenceExpression(TypeReference.ForType(typeof(string))), 
                    "Concat",
                    new CodeVariableReferenceExpression("ROOTNAMESPACE"), 
                    new CodePrimitiveExpression(ns)); 
            }
            else 
            {
                return new CodePrimitiveExpression(ns);
            }
        } 

        private CodeMemberField CreateEntitySetField(EntitySet set) 
        { 
            Debug.Assert(set != null, "Field is Null");
 
            // trying to get
            //
            // private ObjectQuery _Customers = null;
 
            CodeMemberField codeField = new CodeMemberField();
            codeField.Attributes = MemberAttributes.Final | MemberAttributes.Private; 
            codeField.Name = Utils.FieldNameFromPropName(set.Name); 
            AttributeEmitter.AddGeneratedCodeAttribute(codeField);
 
            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);
            codeField.Type = TypeReference.AdoFrameworkGenericClass("DataServiceQuery", genericParameter);
            return codeField;
        } 

        private CodeMemberProperty CreateEntitySetProperty(EntitySet set) 
        { 
            Debug.Assert(set != null, "Property is Null");
 
            // trying to get
            //
            // [System.ComponentModel.Browsable(false)]
            // public ObjectQuery Customers 
            // {
            //      get 
            //      { 
            //          if ((this._Customers == null))
            //          { 
            //              this._Customers = base.CreateQuery("[Customers]");
            //          }
            //          return this._Customers;
            //      } 
            // }
            CodeMemberProperty codeProperty = new CodeMemberProperty(); 
            codeProperty.Attributes = MemberAttributes.Final | GetEntitySetPropertyAccessibility(set); 
            codeProperty.Name = set.Name;
            codeProperty.HasGet = true; 
            codeProperty.HasSet = false;

            // SQLBUDT 598300: property to get query hides a property on base Context?
            if (null != TypeReference.ObjectContextBaseClassType.GetProperty(set.Name)) 
            {
                codeProperty.Attributes |= MemberAttributes.New; 
            } 

            AttributeEmitter.AddBrowsableAttribute(codeProperty); 
            AttributeEmitter.AddGeneratedCodeAttribute(codeProperty);

            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);
            codeProperty.Type = TypeReference.AdoFrameworkGenericClass("DataServiceQuery", 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 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 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(), 
                                "CreateQuery",
                                new CodeTypeReference[] { genericParameter } 
                            ), 
                            new CodePrimitiveExpression(set.Name)
                        ) 
                    )
                )
            );
 
            codeProperty.GetStatements.Add(
                new CodeMethodReturnStatement( 
                    new CodeFieldReferenceExpression( 
                        ThisRef,
                        fieldName 
                    )
                )
            );
 
            // property summary
            CommentEmitter.EmitSummaryComments(set, codeProperty.Comments); 
 
            return codeProperty;
        } 

        /// 
        /// Create an AddTo-EntitysetName methiod for each entityset in the context.
        ///  
        /// EntityContainerEntitySet that we will go over to get the existing entitysets.
        ///  Method definition  
 
        private CodeMemberMethod CreateEntitySetAddObjectMethod(EntitySet set)
        { 
            Debug.Assert(set != null, "Property is Null");

            // trying to get
            // 
            // public void AddToCustomer(Customer customer)
            // { 
            //      base.AddObject("Customer", customer); 
            // }
            CodeMemberMethod codeMethod = new CodeMemberMethod(); 
            codeMethod.Attributes = MemberAttributes.Final | GetEntityTypeAccessibility(set.ElementType);
            codeMethod.Name = ("AddTo" + set.Name);

            CodeParameterDeclarationExpression parameter = new CodeParameterDeclarationExpression(); 

            parameter.Type = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType); 
            parameter.Name = Utils.CamelCase(set.ElementType.Name); 
            parameter.Name = Utils.SetSpecialCaseForFxCopOnPropertyName(parameter.Name);
            codeMethod.Parameters.Add(parameter); 

            codeMethod.ReturnType = new CodeTypeReference(typeof(void));

            AttributeEmitter.AddGeneratedCodeAttribute(codeMethod); 

            codeMethod.Statements.Add( 
                new CodeMethodInvokeExpression( 
                    new CodeBaseReferenceExpression(),
                    "AddObject", 
                    new CodePrimitiveExpression(set.Name),
                    new CodeFieldReferenceExpression(null, parameter.Name)
                )
            ); 

            // method summary 
            CommentEmitter.EmitSummaryComments(set, codeMethod.Comments); 
            return codeMethod;
        } 

        /// 
        /// return a code expression for invoking OnContextCreated partial method
        ///  
        private CodeMethodInvokeExpression OnContextCreatedCodeMethodInvokeExpression()
        { 
            return (new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), _onContextCreatedString, new CodeExpression[] { })); 
        }
 
        /// 
        /// Returns the type specific SchemaElement
        /// 
        private new EntityContainer Item 
        {
            get 
            { 
                return base.Item as EntityContainer;
            } 
        }

        #endregion
    } 
}

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