Пример #1
0
        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);
        }
Пример #2
0
        private void Emit(Dictionary <string, string> usedClassName, string namespaceName, List <GlobalItem> items)
        {
            // it is a valid scenario for namespaceName to be empty
            //string namespaceName = Generator.SourceObjectNamespaceName;
            Generator.SourceEdmNamespaceName = namespaceName;

            // emit the namespace definition
            CodeNamespace codeNamespace = new CodeNamespace(namespaceName);

            // output some boiler plate comments
            string comments = Strings.NamespaceComments(
                System.IO.Path.GetFileName(_targetFilePath),
                DateTime.Now.ToString(System.Globalization.CultureInfo.CurrentCulture));

            CommentEmitter.EmitComments(CommentEmitter.GetFormattedLines(comments, false), codeNamespace.Comments, false);
            CompileUnit.Namespaces.Add(codeNamespace);

            // Emit the classes in the schema
            foreach (GlobalItem element in items)
            {
                if (AddElementNameToCache(element, usedClassName))
                {
                    SchemaTypeEmitter             emitter         = CreateElementEmitter(element);
                    CodeTypeDeclarationCollection typeDeclaration = emitter.EmitApiClass();
                    if (typeDeclaration.Count > 0)
                    {
                        codeNamespace.Types.AddRange(typeDeclaration);
                    }
                }
            }

            Generator.SourceEdmNamespaceName = null;
        }
Пример #3
0
        /// <summary>
        /// Creates the necessary constructors for the entity container.
        /// </summary>
        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);
        }
Пример #4
0
        /// <summary>
        /// Creates the CodeTypeDeclarations necessary to generate the code
        /// </summary>
        public void Emit()
        {
            // it is a valid scenario for namespaceName to be empty
            string namespaceName = Generator.SourceObjectNamespaceName;

            // emit the namespace definition
            CodeNamespace codeNamespace = new CodeNamespace(namespaceName);

            // output some boiler plate comments
            string comments = Strings.NamespaceComments(
                System.IO.Path.GetFileName(_targetFilePath),
                DateTime.Now.ToString(System.Globalization.CultureInfo.CurrentCulture));

            CommentEmitter.EmitComments(CommentEmitter.GetFormattedLines(comments, false), codeNamespace.Comments, false);
            CompileUnit.Namespaces.Add(codeNamespace);

            // Add the assembly attribute.
            CodeAttributeDeclaration assemblyAttribute;

            // SQLBUDT 505339: VB compiler fails if multiple assembly attributes exist in the same project.
            // This adds a GUID to the assembly attribute so that each generated file will have a unique EdmSchemaAttribute in VB.
            if (this.Generator.Language == System.Data.Entity.Design.LanguageOption.GenerateVBCode) //The GUID is only added in VB
            {
                assemblyAttribute = AttributeEmitter.EmitSimpleAttribute("System.Data.Objects.DataClasses.EdmSchemaAttribute", System.Guid.NewGuid().ToString());
            }
            else
            {
                assemblyAttribute = AttributeEmitter.EmitSimpleAttribute("System.Data.Objects.DataClasses.EdmSchemaAttribute");
            }
            CompileUnit.AssemblyCustomAttributes.Add(assemblyAttribute);

            Dictionary <string, string> usedClassName = new Dictionary <string, string>(StringComparer.Ordinal);

            // Emit the classes in the schema
            foreach (GlobalItem element in Generator.GetSourceTypes())
            {
                Debug.Assert(!(element is EdmFunction), "Are you trying to emit functions now? If so add an emitter for it.");

                if (AddElementNameToCache(element, usedClassName))
                {
                    SchemaTypeEmitter             emitter         = CreateElementEmitter(element);
                    CodeTypeDeclarationCollection typeDeclaration = emitter.EmitApiClass();
                    if (typeDeclaration.Count > 0)
                    {
                        codeNamespace.Types.AddRange(typeDeclaration);
                    }
                }
            }
        }
Пример #5
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public override CodeTypeDeclarationCollection EmitApiClass()
        {
            Validate(); // emitter-specific validation

            CodeTypeReference baseType = this.GetBaseType();

            // raise the TypeGenerated event
            TypeGeneratedEventArgs eventArgs = new TypeGeneratedEventArgs(Item, baseType);

            this.Generator.RaiseTypeGeneratedEvent(eventArgs);

            // public [abstract] partial class ClassName
            CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(Item.Name);

            typeDecl.IsPartial      = true;
            typeDecl.TypeAttributes = System.Reflection.TypeAttributes.Class;
            if (Item.Abstract)
            {
                typeDecl.TypeAttributes |= System.Reflection.TypeAttributes.Abstract;
            }

            SetTypeVisibility(typeDecl);

            EmitTypeAttributes(Item.Name, typeDecl, eventArgs.AdditionalAttributes);

            // : baseclass
            AssignBaseType(typeDecl, baseType, eventArgs.BaseType);

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

            CommentEmitter.EmitSummaryComments(Item, typeDecl.Comments);

            // Since abstract types cannot be instantiated, skip the factory method for abstract types
            if ((typeDecl.TypeAttributes & System.Reflection.TypeAttributes.Abstract) == 0)
            {
                EmitFactoryMethod(typeDecl);
            }

            EmitProperties(typeDecl);

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

            CodeTypeDeclarationCollection typeDecls = new CodeTypeDeclarationCollection();

            typeDecls.Add(typeDecl);
            return(typeDecls);
        }
Пример #6
0
        /// <summary>
        /// Create an AddTo-EntitysetName methiod for each entityset in the context.
        /// </summary>
        /// <param name="set">EntityContainerEntitySet that we will go over to get the existing entitysets.</param>
        /// <returns> Method definition </returns>

        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);
        }
Пример #7
0
        /// <summary>
        /// Creates the CodeTypeDeclarations necessary to generate the code for the EntityContainer schema element
        /// </summary>
        /// <returns></returns>
        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);

            CreateConstructors(typeDecl);
            // adding partial OnContextCreated method
            CreateContextPartialMethods(typeDecl);

            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets)
            {
                if (MetadataUtil.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 (MetadataUtil.IsEntitySet(entitySetBase))
                {
                    EntitySet        set          = (EntitySet)entitySetBase;
                    CodeMemberMethod codeProperty = CreateEntitySetAddObjectProperty(set);
                    typeDecl.Members.Add(codeProperty);
                }
            }

            foreach (EdmFunction functionImport in Item.FunctionImports)
            {
                if (ShouldEmitFunctionImport(functionImport))
                {
                    CodeMemberMethod functionMethod = CreateFunctionImportStructuralTypeReaderMethod(functionImport);
                    typeDecl.Members.Add(functionMethod);
                }
            }

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

            CodeTypeDeclarationCollection typeDecls = new CodeTypeDeclarationCollection();

            typeDecls.Add(typeDecl);
            return(typeDecls);
        }
Пример #8
0
        /// <summary>
        /// Create a method entry point for a function import yielding an entity reader.
        /// </summary>
        /// <param name="functionImport">SOM for function import; must not be null and must yield
        /// an entity reader.</param>
        /// <returns>Method definition.</returns>
        private CodeMemberMethod CreateFunctionImportStructuralTypeReaderMethod(EdmFunction functionImport)
        {
            // Trying to get:
            //
            ///// <summary>
            ///// Documentation
            ///// </summary>
            //public ObjectQueryResult<MyType> MyFunctionImport(Nullable<int> id, string foo)
            //{
            //    ObjectParameter idParameter;
            //    if (id.HasValue)
            //    {
            //        idParameter = new ObjectParameter("id", id);
            //    }
            //    else
            //    {
            //        idParameter = new ObjectParameter("id", typeof(int));
            //    }
            //    ObjectParameter fooParameter;
            //    if (null != foo)
            //    {
            //        fooParameter = new ObjectParameter("foo", foo);
            //    }
            //    else
            //    {
            //        fooParameter = new ObjectParameter("foo", typeof(string));
            //    }
            //    return base.ExecuteFunction<MyType>("MyFunctionImport", idParameter, fooParameter);
            //}
            Debug.Assert(null != functionImport);

            CodeMemberMethod method = new CodeMemberMethod();

            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(method);
            method.Name       = functionImport.Name;
            method.Attributes = GetFunctionImportAccessibility(functionImport) | MemberAttributes.Final;

            UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(
                this.Generator.IsLanguageCaseSensitive,
                s => Utils.FixParameterName(s));

            // determine element return type
            EdmType returnType = GetReturnTypeFromFunctionImport(functionImport);

            if (Helper.IsCollectionType(returnType))
            {
                // get the type in the collection
                returnType = ((CollectionType)returnType).TypeUsage.EdmType;
            }
            CodeTypeReference elementType = Generator.GetLeastPossibleQualifiedTypeReference(returnType);

            method.ReturnType = TypeReference.ObjectResult(elementType);

            // generate <summary> comments based on CSDL Documentation element
            CommentEmitter.EmitSummaryComments(functionImport, method.Comments);

            // build up list of arguments to ExecuteFunction
            List <CodeExpression> executeArguments = new List <CodeExpression>();

            executeArguments.Add(new CodePrimitiveExpression(functionImport.Name)); // first argument is the name of the function
            foreach (FunctionParameter parameter in functionImport.Parameters)
            {
                CreateFunctionArgument(method, uniqueIdentifierService, parameter);
            }

            // add fields representing object parameters
            foreach (FunctionParameter parameter in functionImport.Parameters)
            {
                if (parameter.Mode == ParameterMode.In)
                {
                    CodeExpression variableReference = CreateFunctionParameter(method, uniqueIdentifierService, parameter);
                    executeArguments.Add(variableReference);
                }
                else
                {
                    // the parameter is already being passed in as an argument; just remember it and
                    // pass it in as an argument
                    string adjustedParameterName;
                    if (!uniqueIdentifierService.TryGetAdjustedName(parameter, out adjustedParameterName))
                    {
                        Debug.Fail("parameter must be registered in identifier service");
                    }
                    executeArguments.Add(new CodeVariableReferenceExpression(adjustedParameterName));
                }
            }

            // Add call to ExecuteFunction
            //      return ExecuteFunction<elementType>("FunctionImportName", { object parameters });
            CodeMethodReferenceExpression executeFunctionMethod = new CodeMethodReferenceExpression(
                new CodeBaseReferenceExpression(),
                "ExecuteFunction",
                new CodeTypeReference[] { elementType });

            method.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(executeFunctionMethod, executeArguments.ToArray())
                    )
                );

            // invoke the ExecuteFunction method passing in parameters
            return(method);
        }
Пример #9
0
        private CodeMemberProperty CreateEntitySetProperty(EntitySet set)
        {
            Debug.Assert(set != null, "Property is Null");

            // trying to get
            //
            // [System.ComponentModel.Browsable(false)]
            // public ObjectQuery<Customer> Customers
            // {
            //      get
            //      {
            //          if ((this._Customers == null))
            //          {
            //              this._Customers = base.CreateQuery<Customer>("[Customers]");
            //          }
            //          return this._Customers;
            //      }
            // }
            //
            CodeMemberProperty codeProperty = new CodeMemberProperty();

            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(codeProperty);
            codeProperty.Attributes = MemberAttributes.Final | GetEntitySetPropertyAccessibility(set);
            codeProperty.Name       = set.Name;
            codeProperty.HasGet     = true;
            codeProperty.HasSet     = false;

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

            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);

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

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

            Generator.RaisePropertyGeneratedEvent(eventArgs);

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

            List <CodeAttributeDeclaration> additionalAttributes = eventArgs.AdditionalAttributes;

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

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

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

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

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

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

            return(codeProperty);
        }
Пример #10
0
        /// <summary>
        /// Creates the necessary constructors for the entity container.
        /// </summary>
        private void CreateConstructors(CodeTypeDeclaration typeDecl)
        {
            // Empty constructor.
            //
            // public ctor()
            //    : base("name=" + ContainerName, "ContainerName")
            // {
            //      this.OnContextCreated();
            // }
            CodeConstructor emptyCtor = new CodeConstructor();

            emptyCtor.Attributes = MemberAttributes.Public;
            emptyCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression("name=" + Item.Name));
            emptyCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression(Item.Name));
            CommentEmitter.EmitSummaryComments(Strings.EmptyCtorSummaryComment(Item.Name, Item.Name), emptyCtor.Comments);

            emptyCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression());

            typeDecl.Members.Add(emptyCtor);

            // Constructor that takes a connection string.
            //
            // public ctor(string connectionString)
            //    : base(connectionString, "ContainerName")
            // {
            //      this.OnContextCreated();
            // }
            CodeConstructor connectionStringCtor = new CodeConstructor();

            connectionStringCtor.Attributes = MemberAttributes.Public;
            CodeParameterDeclarationExpression connectionStringParam = new CodeParameterDeclarationExpression(TypeReference.String, "connectionString");

            connectionStringCtor.Parameters.Add(connectionStringParam);
            connectionStringCtor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression(connectionStringParam.Name));
            connectionStringCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression(Item.Name));
            CommentEmitter.EmitSummaryComments(Strings.CtorSummaryComment(Item.Name), connectionStringCtor.Comments);

            connectionStringCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression());

            typeDecl.Members.Add(connectionStringCtor);

            // Constructor that takes a connection
            //
            // public ctor(System.Data.EntityClient.EntityConnection connection)
            //    : base(connection, "ContainerName")
            // {
            //      this.OnContextCreated();
            // }
            CodeConstructor connectionWorkspaceCtor = new CodeConstructor();

            connectionWorkspaceCtor.Attributes = MemberAttributes.Public;
            CodeParameterDeclarationExpression connectionParam = new CodeParameterDeclarationExpression(TypeReference.AdoEntityClientType("EntityConnection"), "connection");

            connectionWorkspaceCtor.Parameters.Add(connectionParam);
            connectionWorkspaceCtor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression(connectionParam.Name));
            connectionWorkspaceCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression(Item.Name));
            CommentEmitter.EmitSummaryComments(Strings.CtorSummaryComment(Item.Name), connectionWorkspaceCtor.Comments);

            connectionWorkspaceCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression());
            typeDecl.Members.Add(connectionWorkspaceCtor);
        }
Пример #11
0
        /// <summary>
        /// Emit static factory method which creates an instance of the class and initializes
        /// non-nullable properties (taken as arguments)
        /// </summary>
        /// <param name="typeDecl"></param>
        protected virtual void EmitFactoryMethod(CodeTypeDeclaration typeDecl)
        {
            // build list of non-nullable properties
            ReadOnlyMetadataCollection <EdmProperty> properties = GetProperties();
            List <EdmProperty> parameters = new List <EdmProperty>(properties.Count);

            foreach (EdmProperty property in properties)
            {
                bool include = IncludeFieldInFactoryMethod(property);
                if (include)
                {
                    parameters.Add(property);
                }
            }

            // if there are no parameters, we don't emit anything (1 is for the null element)
            // nor do we emit everything if this is the Ref propertied ctor and the parameter list is the same as the many parametered ctor
            if (parameters.Count < 1)
            {
                return;
            }

            CodeMemberMethod        method  = new CodeMemberMethod();
            CodeTypeReference       typeRef = TypeReference.FromString(Item.Name);
            UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(Generator.IsLanguageCaseSensitive);
            string instanceName = uniqueIdentifierService.AdjustIdentifier(Utils.CamelCase(Item.Name));

            // public static Class CreateClass(...)
            method.Attributes = MemberAttributes.Static | MemberAttributes.Public;
            method.Name       = "Create" + Item.Name;
            if (NavigationPropertyEmitter.IsNameAlreadyAMemberName(Item, method.Name, Generator.LanguageAppropriateStringComparer))
            {
                Generator.AddError(Strings.GeneratedFactoryMethodNameConflict(method.Name, Item.Name),
                                   ModelBuilderErrorCode.GeneratedFactoryMethodNameConflict,
                                   EdmSchemaErrorSeverity.Error);
            }

            method.ReturnType = typeRef;
            AttributeEmitter.AddGeneratedCodeAttribute(method);

            // output method summary comments
            CommentEmitter.EmitSummaryComments(Strings.FactoryMethodSummaryComment(Item.Name), method.Comments);


            // Class class = new Class();
            CodeVariableDeclarationStatement createNewInstance = new CodeVariableDeclarationStatement(
                typeRef, instanceName, new CodeObjectCreateExpression(typeRef));

            method.Statements.Add(createNewInstance);
            CodeVariableReferenceExpression instanceRef = new CodeVariableReferenceExpression(instanceName);

            // iterate over the properties figuring out which need included in the factory method
            foreach (EdmProperty property in parameters)
            {
                // CreateClass( ... , propType propName ...)
                PropertyEmitter   propertyEmitter       = new PropertyEmitter(Generator, property, UsingStandardBaseClass);
                CodeTypeReference propertyTypeReference = propertyEmitter.PropertyType;
                String            parameterName         = uniqueIdentifierService.AdjustIdentifier(Utils.FixParameterName(propertyEmitter.PropertyName, "argument"));
                parameterName = Utils.SetSpecialCaseForFxCopOnPropertyName(parameterName);
                CodeParameterDeclarationExpression paramDecl = new CodeParameterDeclarationExpression(
                    propertyTypeReference, parameterName);
                CodeArgumentReferenceExpression paramRef = new CodeArgumentReferenceExpression(paramDecl.Name);
                method.Parameters.Add(paramDecl);

                // add comment describing the parameter
                CommentEmitter.EmitParamComments(paramDecl, Strings.FactoryParamCommentGeneral(propertyEmitter.PropertyName), method.Comments);

                CodeExpression newPropertyValue;
                if (TypeSemantics.IsComplexType(propertyEmitter.Item.TypeUsage))
                {
                    List <CodeExpression> complexVerifyParameters = new List <CodeExpression>();
                    complexVerifyParameters.Add(paramRef);
                    complexVerifyParameters.Add(new CodePrimitiveExpression(propertyEmitter.PropertyName));

                    // if (null == param) { throw new ArgumentNullException("PropertyName"); }
                    method.Statements.Add(
                        new CodeConditionStatement(
                            EmitExpressionEqualsNull(paramRef),
                            new CodeThrowExceptionStatement(
                                new CodeObjectCreateExpression(
                                    TypeReference.ForType(typeof(ArgumentNullException)),
                                    new CodePrimitiveExpression(parameterName)
                                    )
                                )
                            )
                        );

                    newPropertyValue = paramRef;
                }
                else
                {
                    newPropertyValue = paramRef;
                }

                // Scalar property:
                //     Property = param;
                // Complex property:
                //     Property = StructuralObject.VerifyComplexObjectIsNotNull(param, propertyName);

                method.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(instanceRef, propertyEmitter.PropertyName), newPropertyValue));
            }

            // return class;
            method.Statements.Add(new CodeMethodReturnStatement(instanceRef));

            // actually add the method to the class
            typeDecl.Members.Add(method);
        }
Пример #12
0
        /// <summary>
        /// Generate a navigation property
        /// </summary>
        /// <param name="target">the other end</param>
        /// <param name="referenceProperty">True to emit Reference navigation property</param>
        /// <returns>the generated property</returns>
        private CodeMemberProperty EmitNavigationProperty(RelationshipEndMember target, bool referenceProperty)
        {
            CodeTypeReference typeRef = GetReturnType(target, referenceProperty);

            // raise the PropertyGenerated event
            PropertyGeneratedEventArgs eventArgs = new PropertyGeneratedEventArgs(Item,
                                                                                  null, // no backing field
                                                                                  typeRef);

            this.Generator.RaisePropertyGeneratedEvent(eventArgs);

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

            if (referenceProperty)
            {
                AttributeEmitter.AddBrowsableAttribute(property);
                Generator.AttributeEmitter.EmitGeneratedCodeAttribute(property);
            }
            else
            {
                Generator.AttributeEmitter.EmitNavigationPropertyAttributes(Generator, target, property, eventArgs.AdditionalAttributes);

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

            AttributeEmitter.AddDataMemberAttribute(property);

            CommentEmitter.EmitSummaryComments(Item, property.Comments);

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

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

            property.Attributes = MemberAttributes.Final;

            CodeMethodInvokeExpression getMethod = EmitGetMethod(target);
            CodeExpression             getReturnExpression;

            property.Attributes |= AccessibilityFromGettersAndSetters(Item);
            // setup the accessibility of the navigation property setter and getter
            MemberAttributes propertyAccessibility = property.Attributes & MemberAttributes.AccessMask;

            PropertyEmitter.AddGetterSetterFixUp(Generator.FixUps, GetFullyQualifiedPropertyName(property.Name),
                                                 PropertyEmitter.GetGetterAccessibility(Item), propertyAccessibility, true);
            PropertyEmitter.AddGetterSetterFixUp(Generator.FixUps, GetFullyQualifiedPropertyName(property.Name),
                                                 PropertyEmitter.GetSetterAccessibility(Item), propertyAccessibility, false);

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

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

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

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

                    CodeMethodReferenceExpression initReferenceMethod = new CodeMethodReferenceExpression();
                    initReferenceMethod.MethodName = "InitializeRelatedReference";

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

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

                    property.SetStatements.Add(
                        new CodeConditionStatement(
                            EmitExpressionDoesNotEqualNull(valueRef),
                            new CodeExpressionStatement(
                                new CodeMethodInvokeExpression(
                                    initReferenceMethod, new CodeExpression[] {
                        new CodePrimitiveExpression(cspaceNamespaceNameQualifiedRelationshipName), new CodePrimitiveExpression(target.Name), valueRef
                    }))));
                }
                else
                {
                    CodePropertyReferenceExpression valueProperty = new CodePropertyReferenceExpression(getMethod, ValuePropertyName);

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

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

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

                CodeMethodReferenceExpression initCollectionMethod = new CodeMethodReferenceExpression();
                initCollectionMethod.MethodName = "InitializeRelatedCollection";

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

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

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

            // if additional Get statements were specified by the event subscriber, insert them now
            //
            List <CodeStatement> additionalGetStatements = eventArgs.AdditionalGetStatements;

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

            property.GetStatements.Add(new CodeMethodReturnStatement(getReturnExpression));

            return(property);
        }
        /// <summary>
        /// Generate a navigation property
        /// </summary>
        /// <param name="target">the other end</param>
        /// <param name="referenceProperty">True to emit Reference navigation property</param>
        /// <returns>the generated property</returns>
        private CodeMemberProperty EmitNavigationProperty(RelationshipEndMember target)
        {
            CodeTypeReference typeRef = GetReturnType(target);

            // raise the PropertyGenerated event
            PropertyGeneratedEventArgs eventArgs = new PropertyGeneratedEventArgs(Item,
                                                                                  null, // no backing field
                                                                                  typeRef);

            this.Generator.RaisePropertyGeneratedEvent(eventArgs);

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

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

            AttributeEmitter.AddBrowsableAttribute(property);

            AttributeEmitter.AddGeneratedCodeAttribute(property);

            CommentEmitter.EmitSummaryComments(Item, property.Comments);

            property.Name = Item.Name;

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

            property.Attributes = MemberAttributes.Final;

            CodeExpression getMethod = EmitGetMethod(target);
            CodeExpression getReturnExpression;

            if (target.RelationshipMultiplicity != RelationshipMultiplicity.Many)
            {
                property.Attributes |= AccessibilityFromGettersAndSetters(Item);

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

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


                CodeExpression valueProperty = getMethod;

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

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

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

                List <CodeStatement> additionalAfterSetStatements = eventArgs.AdditionalAfterSetStatements;
                if (additionalAfterSetStatements != null && additionalAfterSetStatements.Count > 0)
                {
                    try
                    {
                        property.SetStatements.AddRange(additionalAfterSetStatements.ToArray());
                    }
                    catch (ArgumentNullException e)
                    {
                        Generator.AddError(Strings.InvalidSetStatementSuppliedForProperty(Item.Name),
                                           ModelBuilderErrorCode.InvalidSetStatementSuppliedForProperty,
                                           EdmSchemaErrorSeverity.Error,
                                           e);
                    }
                }
            }
            else
            {
                property.Attributes |= PropertyEmitter.GetGetterAccessibility(Item);
                // get
                //     return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<TTargetEntity>("CSpaceQualifiedRelationshipName", "TargetRoleName");
                getReturnExpression = getMethod;

                // set
                // if (value != null) ==> Only for non-binding scenario
                // {
                //    this =
                //    this.OnPropertyChanged("")
                // }

                CodeExpression valueRef = new CodePropertySetValueReferenceExpression();

                CodeStatementCollection csc = null;

                if (this.Generator.UseDataServiceCollection == true)
                {
                    csc = property.SetStatements;
                }
                else
                {
                    CodeConditionStatement ccs = new CodeConditionStatement(EmitExpressionDoesNotEqualNull(valueRef));
                    property.SetStatements.Add(ccs);

                    csc = ccs.TrueStatements;
                }

                csc.Add(new CodeAssignStatement(getMethod, valueRef));

                if (eventArgs.AdditionalAfterSetStatements != null)
                {
                    try
                    {
                        foreach (CodeStatement s in eventArgs.AdditionalAfterSetStatements)
                        {
                            csc.Add(s);
                        }
                    }
                    catch (ArgumentNullException e)
                    {
                        Generator.AddError(Strings.InvalidSetStatementSuppliedForProperty(Item.Name),
                                           ModelBuilderErrorCode.InvalidSetStatementSuppliedForProperty,
                                           EdmSchemaErrorSeverity.Error,
                                           e);
                    }
                }
            }

            // if additional Get statements were specified by the event subscriber, insert them now
            //
            List <CodeStatement> additionalGetStatements = eventArgs.AdditionalGetStatements;

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

            property.GetStatements.Add(new CodeMethodReturnStatement(getReturnExpression));

            return(property);
        }
Пример #14
0
        /// <summary>
        /// Creates the CodeTypeDeclarations necessary to generate the code for the EntityContainer schema element
        /// </summary>
        /// <returns></returns>
        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 <StructuralType>()
                    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);
        }
Пример #15
0
        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(Microsoft): 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);
        }