Esempio n. 1
0
        /// <summary>
        /// Gets the contract source file, if one does not exist it will create the partial class file.
        /// </summary>
        /// <param name="source">The visual studio source file to search.</param>
        /// <param name="sourceClass">The target class that contains the contract.</param>
        /// <returns>The target source code or null if it could not be created.</returns>
        public static async Task <CsSource> GetContractSourceFileAsync(VsCSharpSource source, CsClass sourceClass)
        {
            if (source == null)
            {
                return(null);
            }
            if (sourceClass == null)
            {
                return(null);
            }

            var contractFile = GetContractFilePath(sourceClass);

            CsSource result = null;

            if (contractFile.hasFile)
            {
                result = await source.GetCsSourceDocumentFromParent(contractFile.filePath);
            }
            else
            {
                var manager            = source.SourceCode.LoadNamespaceManager(sourceClass.Namespace);
                var partialClassSource = CSharpSourceGenerationCommon.GeneratePartialClass(sourceClass, manager);

                if (string.IsNullOrEmpty(partialClassSource))
                {
                    throw new CodeFactoryException($"Could not generated partial class definition for class {sourceClass.Name}");
                }

                result = await source.AddCSharpCodeFileToParentAsync(partialClassSource,
                                                                     Path.GetFileName(contractFile.filePath));
            }

            return(result);
        }
Esempio n. 2
0
        private async Task <CsSource> AddMethodMember(CsClass targetClass, CsMethod member, bool logging, bool cdf, bool cdfAspNet, string targetFilePath, NamespaceManager manager)
        {
            CsSource result     = null;
            string   sourceCode = null;

            if (cdfAspNet)
            {
                if (WebApiSupport.IsControllerAction(member))
                {
                    sourceCode = CSharpSourceGenerationCommonDeliveryFramework.GenerateControllerActionMethodSourceCode(member,
                                                                                                                        manager, true, true, CsSecurity.Public, logging, "_logger");
                }
                else
                {
                    sourceCode = CSharpSourceGenerationCommonDeliveryFramework.GenerateStandardMethodSourceCode(member,
                                                                                                                manager, true, true, CsSecurity.Public, logging, "_logger");
                }
            }
            else
            {
                if (cdf)
                {
                    sourceCode = CSharpSourceGenerationCommonDeliveryFramework.GenerateStandardMethodSourceCode(member,
                                                                                                                manager, true, true, CsSecurity.Public, logging, "_logger");
                }
                else
                {
                    if (logging)
                    {
                        sourceCode = CSharpSourceGenerationNetCommon.GenerateStandardMethodSourceCode(member,
                                                                                                      manager, true, true, CsSecurity.Public, true, "_logger");
                    }
                    else
                    {
                        sourceCode = CSharpSourceGenerationCommon.GenerateStandardMethodSourceCode(member,
                                                                                                   manager, true, true);
                    }
                }
            }

            if (string.IsNullOrEmpty(sourceCode))
            {
                throw new CodeFactoryException("Was not able to generate the source code for the member method.");
            }

            result = await targetClass.AddToEndAsync(targetFilePath, CsSourceFormatter.IndentCodeBlock(2, sourceCode));

            if (result == null)
            {
                throw new CodeFactoryException("Could not load the source code after adding the member.");
            }

            return(result);
        }
Esempio n. 3
0
        private async Task <CsSource> AddProperty(CsClass targetClass, CsProperty member, string targetFilePath, NamespaceManager manager)
        {
            CsSource result = null;

            string sourceCode = CSharpSourceGenerationCommon.GenerateStandardPropertySourceCode(member, manager);

            if (string.IsNullOrEmpty(sourceCode))
            {
                throw new CodeFactoryException("Was not able to generate the source code for the member property.");
            }

            result = await targetClass.AddToEndAsync(targetFilePath, CsSourceFormatter.IndentCodeBlock(2, sourceCode));

            if (result == null)
            {
                throw new CodeFactoryException("Could not load the source code after adding the member.");
            }

            return(result);
        }
        /// <summary>
        /// Extension method that determines if the logger field is implemented in the class. If it exists will return the provided source. Otherwise will add the logging namespace and the logger field.
        /// </summary>
        /// <param name="source">Source class to check for the logger field.</param>
        /// <param name="loggerName">The name of the logger field to check for.</param>
        /// <param name="parentSourceCode">The source code the class was loaded from.</param>
        /// <returns>The existing source code if the field is found, or the updated source code with the logging field added.</returns>
        public static async Task <CsSource> AddMicrosoftExtensionsLoggerFieldAsync(this CsClass source, string loggerName,
                                                                                   CsSource parentSourceCode)
        {
            //Bounds checking
            if (source == null)
            {
                return(parentSourceCode);
            }
            if (String.IsNullOrEmpty(loggerName))
            {
                return(parentSourceCode);
            }

            //Checking to see if the logger field already exists. If it does just return the parent source code.
            if (source.HasMicrosoftExtensionsLoggerField(loggerName))
            {
                return(parentSourceCode);
            }

            //Adding the logging namespace
            var currentSource = await parentSourceCode.AddUsingStatementAsync(NetConstants.MicrosoftLoggerNamespace);

            var currentClass = currentSource.GetModel(source.LookupPath) as CsClass;

            if (currentClass == null)
            {
                throw new CodeFactoryException("Cannot load class data to add the logger field.");
            }

            CodeFactory.SourceFormatter fieldSource = new CodeFactory.SourceFormatter();

            fieldSource.AppendCodeLine(2, "/// <summary>");
            fieldSource.AppendCodeLine(2, "/// Logger for all logging interactions in the class.");
            fieldSource.AppendCodeLine(2, "/// </summary>");
            fieldSource.AppendCodeLine(2, $"private readonly {NetConstants.MicrosoftLoggerInterfaceName} {loggerName};");
            fieldSource.AppendCodeLine(0);

            currentSource = await currentClass.AddToBeginningAsync(fieldSource.ReturnSource());

            return(currentSource);
        }
Esempio n. 5
0
        private async Task <CsSource> UpdateSubscriptionAsync(CsField subscriptionField, CsClass sourceClass, VsCSharpSource source)
        {
            SourceFormatter formatter        = new SourceFormatter();
            string          injectSourceCode = null;

            var contract = subscriptionField.DataType.GetInterfaceModel();

            if (contract == null)
            {
                return(null);
            }

            CsSource sourceCode = source.SourceCode;

            try
            {
                CsClass currentClass = sourceClass;

                var events = contract.Events;

                var subscribePath = ContractHelper.GetSubscribeFilePath(currentClass);


                if (!subscribePath.hasFile)
                {
                    var manager = sourceCode.LoadNamespaceManager(sourceClass.Namespace);

                    var parent = await source.GetParentAsync();

                    if (parent == null)
                    {
                        throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                    }

                    VsDocument generatedDocument  = null;
                    string     partialClassSource = CSharpSourceGenerationCommon.GeneratePartialClass(currentClass, manager);
                    if (parent.ModelType == VisualStudioModelType.ProjectFolder)
                    {
                        var parentFolder = parent as VsProjectFolder;

                        if (parentFolder == null)
                        {
                            throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                        }

                        generatedDocument = await parentFolder.AddDocumentAsync(Path.GetFileName(subscribePath.filePath),
                                                                                partialClassSource);
                    }
                    else
                    {
                        var parentProject = parent as VsProject;

                        if (parentProject == null)
                        {
                            throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                        }

                        generatedDocument = await parentProject.AddDocumentAsync(subscribePath.filePath,
                                                                                 partialClassSource);
                    }
                    sourceCode = await generatedDocument.GetCSharpSourceModelAsync();

                    sourceCode = await sourceCode.AddMissingNamespaces(contract.Events, currentClass.Namespace);

                    currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass;

                    if (currentClass == null)
                    {
                        throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                    }
                }
                else
                {
                    var parent = await source.GetParentAsync();

                    VsCSharpSource sourceDocument = null;
                    if (parent.ModelType == VisualStudioModelType.ProjectFolder)
                    {
                        var parentFolder = parent as VsProjectFolder;

                        if (parentFolder == null)
                        {
                            throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                        }

                        var children = await parentFolder.GetChildrenAsync(false, true);

                        sourceDocument = children.Where(c => c.ModelType == VisualStudioModelType.CSharpSource)
                                         .Cast <VsCSharpSource>()
                                         .FirstOrDefault(s => s.SourceCode.SourceDocument == subscribePath.filePath);
                    }
                    else
                    {
                        var parentProject = parent as VsProject;

                        if (parentProject == null)
                        {
                            throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                        }

                        var children = await parentProject.GetChildrenAsync(false, true);

                        sourceDocument = children.Where(c => c.ModelType == VisualStudioModelType.CSharpSource)
                                         .Cast <VsCSharpSource>()
                                         .FirstOrDefault(s => s.SourceCode.SourceDocument == subscribePath.filePath);;
                    }

                    if (sourceDocument == null)
                    {
                        throw new CodeFactoryException("Could load the contract document.");
                    }

                    sourceCode = sourceDocument.SourceCode;

                    sourceCode = await sourceCode.AddMissingNamespaces(contract.Events, currentClass.Namespace);

                    currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass;
                    if (currentClass == null)
                    {
                        throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                    }
                }

                var namespaceManager = sourceCode.LoadNamespaceManager(currentClass.Namespace);

                foreach (var contractEvent in contract.Events)
                {
                    var eventHandlerName =
                        CSharpSourceGenerationWPF.GenerateContractEventHandlerMethodName(subscriptionField, contractEvent);

                    if (eventHandlerName == null)
                    {
                        throw new CodeFactoryException($"Could not create the source code for a contract event handler.");
                    }

                    if (currentClass.Methods.Any(m => m.Name == eventHandlerName))
                    {
                        continue;
                    }

                    var eventHandlerSource = CSharpSourceGenerationWPF.GenerateContractEventHandlerMethod(subscriptionField, contractEvent,
                                                                                                          namespaceManager);

                    if (eventHandlerSource == null)
                    {
                        throw new CodeFactoryException($"Could not create the source code for the event handler {eventHandlerName}");
                    }

                    sourceCode = await currentClass.AddToEndAsync(subscribePath.filePath, InjectSourceCodeAtLevel(2, eventHandlerSource));

                    currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass;
                    if (currentClass == null)
                    {
                        throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                    }
                }

                var subscriptionName   = CSharpSourceGenerationWPF.GenerateContractSubscriptionMethodName(subscriptionField);
                var subscriptionMethod = currentClass.Methods.FirstOrDefault(m => m.Name == subscriptionName);

                if (subscriptionMethod != null)
                {
                    sourceCode = await subscriptionMethod.DeleteAsync();

                    currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass;
                    if (currentClass == null)
                    {
                        throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                    }
                }

                var subscriptionSource = CSharpSourceGenerationWPF.GenerateContractSubscriptionMethod(subscriptionField, contract);

                if (subscriptionSource == null)
                {
                    throw new CodeFactoryException("Cannot generate the subscription contract source code.");
                }

                sourceCode = await currentClass.AddToEndAsync(subscribePath.filePath, InjectSourceCodeAtLevel(2, subscriptionSource));

                currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass;
                if (currentClass == null)
                {
                    throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                }

                var releaseName   = CSharpSourceGenerationWPF.GenerateContractReleaseMethodName(subscriptionField);
                var releaseMethod = currentClass.Methods.FirstOrDefault(m => m.Name == releaseName);

                if (releaseMethod != null)
                {
                    sourceCode = await releaseMethod.DeleteAsync();

                    currentClass = sourceCode.GetModel(currentClass.LookupPath) as CsClass;
                    if (currentClass == null)
                    {
                        throw new CodeFactoryException("Cannot access the parent of the source code document, cannot update subscription");
                    }
                }

                var releaseSource = CSharpSourceGenerationWPF.GenerateContractReleaseMethod(subscriptionField, contract);

                if (releaseSource == null)
                {
                    throw new CodeFactoryException("Cannot generate the release contract source code.");
                }

                sourceCode = await currentClass.AddToEndAsync(subscribePath.filePath, InjectSourceCodeAtLevel(2, releaseSource));
            }
            catch (CodeFactoryException)
            {
                throw;
            }
            catch (Exception unhandledException)
            {
                throw new CodeFactoryException("The following unhandledException occured", unhandledException);
            }

            return(sourceCode);
        }
Esempio n. 6
0
 /// <summary>
 /// Constructor for the base class <see cref="VsCSharpSource"/>
 /// </summary>
 /// <param name="isLoaded">Flag that determines if the model is loaded.</param>
 /// <param name="hasErrors">Flag that determines if errors occured while loading the model.</param>
 /// <param name="modelErrors">The list of errors that occured if any.</param>
 /// <param name="name">The name of the model.</param>
 /// <param name="sourceCode">The loaded C# model data.</param>
 protected VsCSharpSource(bool isLoaded, bool hasErrors,
                          IReadOnlyList <ModelException <VisualStudioModelType> > modelErrors, string name,
                          CsSource sourceCode) : base(isLoaded, hasErrors, modelErrors, VisualStudioModelType.CSharpSource, name)
 {
     _sourceCode = sourceCode;
 }
Esempio n. 7
0
        private async Task <CsSource> AddEvent(CsClass targetClass, CsEvent member, bool isContractMember,
                                               string targetFilePath, NamespaceManager manager)
        {
            CsSource result          = null;
            CsClass  currentClass    = targetClass;
            string   eventSourceCode = null;

            string eventFieldName = null;

            if (isContractMember)
            {
                string fieldPrefix = "_";
                string fieldSuffix = "Handler";

                eventFieldName = $"{fieldPrefix}{member.Name.ConvertToCamelCase()}{fieldSuffix}";

                if (!currentClass.Fields.Any(f => f.Name == eventFieldName))
                {
                    string fieldSource = $"private {member.EventType.CSharpFormatTypeName(manager)} {eventFieldName};";

                    result = await currentClass.AddToBeginningAsync(targetFilePath,
                                                                    CsSourceFormatter.IndentCodeBlock(2, fieldSource));

                    currentClass = result.GetModel(currentClass.LookupPath) as CsClass;
                    if (currentClass == null)
                    {
                        throw new CodeFactoryException("Could not load class data cannot update members.");
                    }
                }

                eventSourceCode = CSharpSourceGenerationCommon.GenerateAddRemoveEvent(member, manager,
                                                                                      CsSecurity.Public, fieldPrefix, fieldSuffix);
            }
            else
            {
                eventSourceCode = CSharpSourceGenerationCommon.GenerateStandardEventSourceCode(member, manager);
            }

            if (string.IsNullOrEmpty(eventSourceCode))
            {
                throw new CodeFactoryException("Could not generate the event source code.");
            }

            result = await currentClass.AddToEndAsync(targetFilePath, CsSourceFormatter.IndentCodeBlock(2, eventSourceCode));

            currentClass = result.GetModel(currentClass.LookupPath) as CsClass;
            if (currentClass == null)
            {
                throw new CodeFactoryException("Could not load class data cannot update members.");
            }

            string raiseEventSourceCode = null;

            if (isContractMember)
            {
                if (string.IsNullOrEmpty(eventFieldName))
                {
                    throw new CodeFactoryException("Event field name was not provided cannot create event handler");
                }

                raiseEventSourceCode = CSharpSourceGenerationCommon.GenerateStandardRaiseEventMethod(member, manager, member.Name,
                                                                                                     CsSecurity.Protected, eventFieldName);
            }
            else
            {
                raiseEventSourceCode = CSharpSourceGenerationCommon.GenerateStandardRaiseEventMethod(member, manager, member.Name,
                                                                                                     CsSecurity.Protected);
            }

            result = await currentClass.AddToEndAsync(targetFilePath,
                                                      CsSourceFormatter.IndentCodeBlock(2, raiseEventSourceCode));

            return(result);
        }
Esempio n. 8
0
        private async Task <CsSource> UpdateMembersAsync(CsClass targetClass, IEnumerable <CsMember> members, bool logging, bool cdf, bool cdfAspnet, string targetFilePath, bool isContract, NamespaceManager manager)
        {
            if (targetClass == null)
            {
                return(null);
            }
            if (members == null)
            {
                return(null);
            }
            if (!members.Any())
            {
                return(null);
            }

            if (string.IsNullOrEmpty(targetFilePath))
            {
                return(null);
            }

            CsSource updatedSource = null;
            CsClass  updatedClass  = targetClass;

            foreach (var csMember in members)
            {
                switch (csMember.MemberType)
                {
                case CsMemberType.Event:

                    CsEvent eventData = csMember as CsEvent;

                    if (eventData == null)
                    {
                        throw new CodeFactoryException("Cannot load event data, cannot process members.");
                    }

                    updatedSource = await AddEvent(updatedClass, eventData, isContract, targetFilePath, manager);

                    updatedClass = updatedSource.GetModel(updatedClass.LookupPath) as CsClass;
                    if (updatedClass == null)
                    {
                        throw new CodeFactoryException("Could not load class data cannot add members.");
                    }

                    break;

                case CsMemberType.Method:

                    CsMethod methodData = csMember as CsMethod;

                    if (methodData == null)
                    {
                        throw new CodeFactoryException("Cannot load method data, cannot process members.");
                    }

                    updatedSource = await AddMethodMember(updatedClass, methodData, logging, cdf, cdfAspnet,
                                                          targetFilePath, manager);

                    updatedClass = updatedSource.GetModel(updatedClass.LookupPath) as CsClass;
                    if (updatedClass == null)
                    {
                        throw new CodeFactoryException("Could not load class data cannot add members.");
                    }

                    break;

                case CsMemberType.Property:

                    CsProperty propertyData = csMember as CsProperty;

                    if (propertyData == null)
                    {
                        throw new CodeFactoryException("Cannot load property data, cannot process members.");
                    }

                    updatedSource = await AddProperty(updatedClass, propertyData, targetFilePath, manager);

                    updatedClass = updatedSource.GetModel(updatedClass.LookupPath) as CsClass;
                    if (updatedClass == null)
                    {
                        throw new CodeFactoryException("Could not load class data cannot add members.");
                    }

                    break;

                default:
                    continue;
                }
            }

            return(updatedSource);
        }
Esempio n. 9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="targetClass"></param>
        /// <param name="sourceCode"></param>
        /// <param name="members"></param>
        /// <param name="logging"></param>
        /// <param name="cdf"></param>
        /// <param name="cdfAspnet"></param>
        /// <param name="isContract"></param>
        /// <returns></returns>
        private async Task <CsSource> UpdateFileAsync(CsClass targetClass, CsSource sourceCode, IEnumerable <CsMember> members, bool logging, bool cdf, bool cdfAspnet, bool isContract)
        {
            if (targetClass == null)
            {
                throw new CodeFactoryException("Cannot access class data cannot add members");
            }
            if (sourceCode == null)
            {
                throw new CodeFactoryException("Cannot access the classes source code cannot add members.");
            }
            if (members == null)
            {
                return(sourceCode);
            }
            if (!members.Any())
            {
                return(sourceCode);
            }

            CsSource updatedSourceCode = await sourceCode.AddMissingNamespaces(members, targetClass.Namespace);

            CsClass updatedClass = targetClass;



            if (logging)
            {
                updatedSourceCode = await updatedSourceCode.AddUsingStatementAsync(NetConstants.MicrosoftLoggerNamespace);

                updatedClass = sourceCode.GetModel(updatedClass.LookupPath) as CsClass;
                if (updatedClass == null)
                {
                    throw new CodeFactoryException("Cannot get class data to add members.");
                }

                if (!updatedClass.Fields.Any(f => f.Name == NetConstants.DefaultClassLoggerName))
                {
                    var formatter = new SourceFormatter();
                    formatter.AppendCodeLine(0, "///<summary>");
                    formatter.AppendCodeLine(0, "///Logger used to manage logging for this class.");
                    formatter.AppendCodeLine(0, "///</summary>");
                    formatter.AppendCodeLine(0, $"private ILogger {NetConstants.DefaultClassLoggerName};");
                    updatedSourceCode =
                        await updatedClass.AddToBeginningAsync(
                            CsSourceFormatter.IndentCodeBlock(2, formatter.ReturnSource()));
                }
            }

            if (cdf)
            {
                updatedSourceCode = await updatedSourceCode.AddUsingStatementAsync(CommonDeliveryFrameworkConstants
                                                                                   .CommonDeliveryFrameworkNamespace);
            }

            if (cdfAspnet)
            {
                updatedSourceCode = await updatedSourceCode.AddUsingStatementAsync(CommonDeliveryFrameworkConstants
                                                                                   .CommonDeliveryFrameworkNetAspNetNamespace);
            }

            updatedClass = sourceCode.GetModel(updatedClass.LookupPath) as CsClass;
            if (updatedClass == null)
            {
                throw new CodeFactoryException("Cannot get class data to add members.");
            }

            updatedSourceCode = await UpdateMembersAsync(updatedClass, members, logging, cdf, cdfAspnet,
                                                         updatedSourceCode.SourceDocument, isContract, sourceCode.LoadNamespaceManager(updatedClass.Namespace));

            return(updatedSourceCode);
        }
        /// <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);
        }
Esempio n. 11
0
        /// <summary>
        /// Searches the root of a project for the dependency injection registration class. If it is not found will generate a new service registration class.
        /// </summary>
        /// <param name="source">The source project to load the registration class from.</param>
        /// <param name="className">The name of the class that is used for service registration. This will be set to the constant <see cref="NetConstants.DefaultDependencyInjectionClassName"/> this can be overwritten with a custom class name.</param>
        /// <param name="automatedRegistrationMethodName">The name of the automatic transient class registration method. This will be set to the constant <see cref="NetConstants.DefaultAutomaticTransientClassRegistrationMethodName"/> this can be overwritten with a custom method name. </param>
        /// <returns>The source code model for the registration class.</returns>
        public static async Task <CsSource> GetRegistrationClassAsync(VsProject source, string className     = NetConstants.DefaultDependencyInjectionClassName,
                                                                      string automatedRegistrationMethodName = NetConstants.DefaultAutomaticTransientClassRegistrationMethodName)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (!source.IsLoaded)
            {
                throw new CodeFactoryException("Project model was not loaded cannot load or create the registration class.");
            }
            if (string.IsNullOrEmpty(className))
            {
                throw new ArgumentNullException(nameof(className));
            }

            var projectFiles = await source.GetChildrenAsync(false, true);

            CsSource registrationSource = null;

            try
            {
                //Searching the projects root directory code files for the registration class
                if (projectFiles.Any())
                {
                    registrationSource = projectFiles.Where(f => f.ModelType == VisualStudioModelType.CSharpSource)
                                         .Cast <VsCSharpSource>().FirstOrDefault(s => s.SourceCode.Classes.Any(c => c.Name == className))
                                         ?.SourceCode;
                }

                //If no registration source code file was found then create a new registration class from scratch.
                if (registrationSource == null)
                {
                    var registrationClassCode = BuildNewRegistrationClass(source, className, automatedRegistrationMethodName);
                    if (registrationClassCode == null)
                    {
                        throw new CodeFactoryException("Could not generate the dependency injection registration source code");
                    }
                    string registrationClassFileName = $"{className}.cs";

                    var document = await source.AddDocumentAsync(registrationClassFileName, registrationClassCode);

                    registrationSource = await document.GetCSharpSourceModelAsync();
                }

                if (registrationSource == null)
                {
                    throw new CodeFactoryException("Cannot load the source code for the registration class.");
                }
            }
            catch (CodeFactoryException)
            {
                throw;
            }
            catch (Exception unhandledException)
            {
                throw new CodeFactoryException("An error occured while loading the registration class source code, cannot continue.", unhandledException);
            }

            return(registrationSource);
        }
 /// <summary>
 /// Creates a new instance of a namespace manager from a target model
 /// </summary>
 /// <param name="source">The model to load from.</param>
 /// <param name="targetNamespace">The target namespace the manager supports.</param>
 /// <returns>New instance of the namespace manager.</returns>
 public static NamespaceManager LoadNamespaceManager(this CsSource source, string targetNamespace = null)
 {
     return(source == null ? new NamespaceManager(null) : new NamespaceManager(source.NamespaceReferences, targetNamespace));
 }