/// <summary>
        /// Adds the missing members to a target class, that support the common delivery framework implementation..
        /// </summary>
        /// <param name="source">The source code that contains the target class to be updated.</param>
        /// <param name="targetClass">The target class to have the members added to.</param>
        /// <param name="missingMembers">The missing members to be added to the target class.</param>
        /// <param name="boundsCheckLogic">Optional parameter that determines if bounds checking logic should be added to methods. This will default to true.</param>
        /// <param name="loggingLogic">Optional parameter that determines if enter, exit and exception management logic should be added to methods.</param>
        /// <param name="supportAsyncMethods">Optional parameter that determines if methods will use the async keyword when support multi-threaded operations.</param>
        /// <param name="supportsCDFAspNet">Optional parameters that determines if add members support aspnet error handling with CommonDeliveryFramework.</param>
        /// <returns>The updated SourceCode Model once the missing members have been added.</returns>
        /// <exception cref="ArgumentNullException">Thrown if data needed to process a member is not passed.</exception>
        /// <exception cref="CodeFactoryException">Thrown is model data is not valid or a processing error occurs.</exception>
        public static async Task <CsSource> AddMembersToClassWithCDFSupportAsync(CsSource source, CsClass targetClass,
                                                                                 IReadOnlyList <CsMember> missingMembers, bool boundsCheckLogic = true, bool loggingLogic = true, bool supportAsyncMethods = true, bool supportsCDFAspNet = false)
        {
            //Bounds checking to confirm all needed data was passed.
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (targetClass == null)
            {
                throw new ArgumentNullException(nameof(targetClass));
            }
            if (missingMembers == null)
            {
                throw new ArgumentNullException(nameof(missingMembers));
            }

            //Confirming the target models are loaded and are source code
            if (!source.IsLoaded)
            {
                throw new CodeFactoryException("Source code model was not loaded.");
            }
            if (!targetClass.IsLoaded)
            {
                throw new CodeFactoryException("The target class model data is not loaded.");
            }
            if (!targetClass.LoadedFromSource)
            {
                throw new CodeFactoryException("Target class is not loaded from source code cannot update.");
            }

            //If an empty list of missing members was provided then return the original source code
            if (!missingMembers.Any())
            {
                return(source);
            }

            //Variables used to hold the most current version of the code factory models that are being updated.
            CsClass  currentClassModel  = targetClass;
            CsSource currentSourceModel = source;

            currentSourceModel = await currentSourceModel.AddMissingNamespaces(missingMembers, currentClassModel.Namespace);

            currentClassModel = currentSourceModel.GetModel(currentClassModel.LookupPath) as CsClass;
            if (currentClassModel == null)
            {
                throw new CodeFactoryException("Cannot load class data, cannot complete adding interface members");
            }

            //Checking to make sure there is a logger field implemented if not add it to the class.
            currentSourceModel = await currentClassModel.AddMicrosoftExtensionsLoggerFieldAsync(AspNetCoreConstants.FieldNameLogger,
                                                                                                currentSourceModel);

            currentClassModel = currentSourceModel.GetModel(currentClassModel.LookupPath) as CsClass;
            if (currentClassModel == null)
            {
                throw new CodeFactoryException("Cannot load class data, cannot complete adding interface members");
            }


            currentSourceModel = await currentSourceModel.AddUsingStatementAsync(AspNetCoreConstants.CommonDeliveryFrameworkLibraryName);

            currentClassModel = currentSourceModel.GetModel(currentClassModel.LookupPath) as CsClass;
            if (currentClassModel == null)
            {
                throw new CodeFactoryException("Cannot load class data, cannot complete adding interface members");
            }

            if (supportsCDFAspNet)
            {
                //Confirming CDF ASPnet namespace is added to the code file.
                currentSourceModel = await currentSourceModel.AddUsingStatementAsync(AspNetCoreConstants.CommonDeliveryFrameworkAspNetLibraryName);

                currentClassModel = currentSourceModel.GetModel(currentClassModel.LookupPath) as CsClass;
                if (currentClassModel == null)
                {
                    throw new CodeFactoryException("Cannot load class data, cannot complete adding interface members");
                }

                //Confirming the mvc namespace is added to the code file.
                currentSourceModel = await currentSourceModel.AddUsingStatementAsync(AspNetCoreConstants.MvcNamespace);

                currentClassModel = currentSourceModel.GetModel(currentClassModel.LookupPath) as CsClass;
                if (currentClassModel == null)
                {
                    throw new CodeFactoryException("Cannot load class data, cannot complete adding interface members");
                }
            }

            if (supportAsyncMethods)
            {
                //Confirming the mvc namespace is added to the code file.
                currentSourceModel = await currentSourceModel.AddUsingStatementAsync(AspNetCoreConstants.SystemThreadingTasksNamespace);

                currentClassModel = currentSourceModel.GetModel(currentClassModel.LookupPath) as CsClass;
                if (currentClassModel == null)
                {
                    throw new CodeFactoryException("Cannot load class data, cannot complete adding interface members");
                }
            }

            //Loading a namespace manager that will update types definitions to use the correct namespace format. This reads in all the using statements assigned to the class.
            var namespaceManager = source.LoadNamespaceManager(currentClassModel.Namespace);

            bool isControllerClass = currentClassModel.IsController();

            //Processing the missing members
            foreach (var member in missingMembers)
            {
                //Clearing the formatted source code for the member before processing each member
                string sourceCode = null;

                switch (member.MemberType)
                {
                case CsMemberType.Event:

                    //Validating the member event model loaded correctly if not return to the top. No exception will be thrown.
                    if (!(member is CsEvent eventModel))
                    {
                        continue;
                    }

                    //Formatting a default event definition.
                    sourceCode = FormatMemberEvent(eventModel, namespaceManager);

                    break;

                case CsMemberType.Method:

                    //Validating the member event model loaded correctly if not return to the top. No exception will be thrown.
                    if (!(member is CsMethod methodModel))
                    {
                        continue;
                    }

                    bool isControllerAction = false;

                    if (supportsCDFAspNet & isControllerClass)
                    {
                        isControllerAction = IsControllerAction(methodModel);
                    }

                    //Formatting the method implementation based on the optional parameters provided.
                    sourceCode = FormatMemberMethod(methodModel, namespaceManager, loggingLogic, boundsCheckLogic,
                                                    supportAsyncMethods, isControllerAction);

                    break;

                case CsMemberType.Property:

                    //Validating the member property model loaded correctly if not return to the top. No exception will be thrown.
                    if (!(member is CsProperty propertyModel))
                    {
                        continue;
                    }

                    //Formatting a default property definition.
                    sourceCode = FormatMemberProperty(propertyModel, namespaceManager);

                    break;

                default:
                    continue;
                }

                if (string.IsNullOrEmpty(sourceCode))
                {
                    continue;
                }

                //Creating a source formatter and appending the final output with two indent levels to within the body over a class.
                var sourceFormatter = new CodeFactory.SourceFormatter();

                sourceFormatter.AppendCodeBlock(2, sourceCode);

                currentSourceModel = await currentClassModel.AddToEndAsync(sourceFormatter.ReturnSource());

                if (currentSourceModel == null)
                {
                    throw new CodeFactoryException("Cannot load the source code file, cannot complete adding interface members");
                }

                currentClassModel = currentSourceModel.GetModel(currentClassModel.LookupPath) as CsClass;
                if (currentClassModel == null)
                {
                    throw new CodeFactoryException("Cannot load class data, cannot complete adding interface members");
                }
            }

            return(currentSourceModel);
        }