コード例 #1
0
        public static ModelType ValidateType(string typeName,
                                             string argumentName,
                                             IModelTypesLocator modelTypesLocator,
                                             bool throwWhenNotFound = true)
        {
            if (string.IsNullOrEmpty(typeName))
            {
                throw new ArgumentException(string.Format("Please provide a valid {0}", argumentName));
            }

            var candidateModelTypes = modelTypesLocator.GetType(typeName).ToList();

            int count = candidateModelTypes.Count;

            if (count == 0)
            {
                if (throwWhenNotFound)
                {
                    throw new ArgumentException(string.Format("A type with the name {0} does not exist", typeName));
                }
                return(null);
            }

            if (count > 1)
            {
                throw new ArgumentException(string.Format(
                                                "Multiple types matching the name {0} exist:{1}, please use a fully qualified name",
                                                typeName,
                                                string.Join(",", candidateModelTypes.Select(t => t.Name).ToArray())));
            }

            return(candidateModelTypes.First());
        }
コード例 #2
0
        public static ModelType ValidateType(string typeName,
            string argumentName,
            IModelTypesLocator modelTypesLocator,
            bool throwWhenNotFound = true)
        {
            if (string.IsNullOrEmpty(typeName))
            {
                throw new ArgumentException(string.Format(CodeGenerators.Mvc.MessageStrings.ProvideValidArgument, argumentName));
            }

            var candidateModelTypes = modelTypesLocator.GetType(typeName).ToList();

            int count = candidateModelTypes.Count;
            if (count == 0)
            {
                if (throwWhenNotFound)
                {
                    throw new ArgumentException(string.Format(CodeGenerators.Mvc.MessageStrings.TypeDoesNotExist, typeName));
                }
                return null;
            }

            if (count > 1)
            {
                throw new ArgumentException(string.Format(
                    "Multiple types matching the name {0} exist:{1}, please use a fully qualified name",
                    typeName,
                    string.Join(",", candidateModelTypes.Select(t => t.Name).ToArray())));
            }

            return candidateModelTypes.First();
        }
コード例 #3
0
        public async Task <bool> GenerateStartupOrReadme(List <StartupContent> startupList)
        {
            var startupTypes = _modelTypesLocator.GetType(Constants.StartupClassName);

            if (startupTypes.Any())
            {
                await GenerateReadMe(startupList);

                return(true);
            }
            else
            {
                await GenerateStartup(startupList);

                return(false);
            }
        }
コード例 #4
0
        public async void TestGetModelMetadata_WithDbContext()
        {
            using (var fileProvider = new TemporaryFileProvider())
            {
                SetupProjects(fileProvider);

                var appName    = MsBuildProjectStrings.RootProjectName;
                var path       = Path.Combine(fileProvider.Root, "Root", appName);
                var efServices = GetEfServices(path, appName);

                var modelType = _modelTypesLocator.GetType("Library1.Models.Car").First();
                var metadata  = await efServices.GetModelMetadata("TestProject.Models.CarContext", modelType, string.Empty);

                Assert.Equal(ContextProcessingStatus.ContextAvailable, metadata.ContextProcessingStatus);
                Assert.Equal(3, metadata.ModelMetadata.Properties.Length);
            }
        }
コード例 #5
0
ファイル: ValidationUtil.cs プロジェクト: nsavga/Scaffolding
        public static bool TryValidateType(string typeName,
                                           string argumentName,
                                           IModelTypesLocator modelTypesLocator,
                                           out ITypeSymbol type,
                                           out string errorMessage)
        {
            errorMessage = string.Empty;
            type         = null;

            if (string.IsNullOrEmpty(typeName))
            {
                //Perhaps for these kind of checks, the validation could be in the API.
                errorMessage = string.Format("Please provide a valid {0}", argumentName);
                return(false);
            }

            var candidateModelTypes = modelTypesLocator.GetType(typeName).ToList();

            int count = candidateModelTypes.Count;

            if (count == 0)
            {
                errorMessage = string.Format("A type with the name {0} does not exist", typeName);
                return(false);
            }

            if (count > 1)
            {
                errorMessage = string.Format(
                    "Multiple types matching the name {0} exist:{1}, please use a fully qualified name",
                    typeName,
                    string.Join(",", candidateModelTypes.Select(t => t.Name).ToArray()));
                return(false);
            }

            type = candidateModelTypes.First();
            return(true);
        }
コード例 #6
0
        public static ModelType ValidateType(string typeName,
                                             string argumentName,
                                             IModelTypesLocator modelTypesLocator,
                                             bool throwWhenNotFound = true)
        {
            if (string.IsNullOrEmpty(typeName))
            {
                throw new ArgumentException(string.Format(MessageStrings.ProvideValidArgument, argumentName));
            }

            if (modelTypesLocator == null)
            {
                throw new ArgumentNullException(nameof(modelTypesLocator));
            }

            var candidateModelTypes = modelTypesLocator.GetType(typeName).ToList();

            int count = candidateModelTypes.Count;

            if (count == 0)
            {
                if (throwWhenNotFound)
                {
                    throw new ArgumentException(string.Format(MessageStrings.TypeDoesNotExist, typeName));
                }
                return(null);
            }

            if (count > 1)
            {
                throw new ArgumentException(string.Format(
                                                MessageStrings.MultipleTypesMatchingName,
                                                typeName,
                                                string.Join(",", candidateModelTypes.Select(t => t.Name).ToArray())));
            }

            return(candidateModelTypes.First());
        }
コード例 #7
0
        public async Task <ContextProcessingResult> GetModelMetadata(string dbContextFullTypeName, ModelType modelTypeSymbol)
        {
            Type       dbContextType;
            SyntaxTree dbContextSyntaxTree = null;

            EditSyntaxTreeResult startUpEditResult = new EditSyntaxTreeResult()
            {
                Edited = false
            };

            ContextProcessingStatus state = ContextProcessingStatus.ContextAvailable;

            var  dbContextSymbols    = _modelTypesLocator.GetType(dbContextFullTypeName).ToList();
            var  startupType         = _modelTypesLocator.GetType("Startup").FirstOrDefault();
            Type modelReflectionType = null;

            if (dbContextSymbols.Count == 0)
            {
                await ValidateEFSqlServerDependency();

                // Create a new Context
                _logger.LogMessage("Generating a new DbContext class " + dbContextFullTypeName);
                var dbContextTemplateModel = new NewDbContextTemplateModel(dbContextFullTypeName, modelTypeSymbol);
                dbContextSyntaxTree = await _dbContextEditorServices.AddNewContext(dbContextTemplateModel);

                state = ContextProcessingStatus.ContextAdded;

                // Edit startup class to register the context using DI
                if (startupType != null)
                {
                    startUpEditResult = _dbContextEditorServices.EditStartupForNewContext(startupType,
                                                                                          dbContextTemplateModel.DbContextTypeName,
                                                                                          dbContextTemplateModel.DbContextNamespace,
                                                                                          dataBaseName: dbContextTemplateModel.DbContextTypeName + "-" + Guid.NewGuid().ToString());
                }

                if (!startUpEditResult.Edited)
                {
                    state = ContextProcessingStatus.ContextAddedButRequiresConfig;

                    // The created context would anyway fail to fetch metadata with a crypic message
                    // It's better to throw with a meaningful message
                    throw new InvalidOperationException(string.Format("{0} {1}", MessageStrings.FailedToEditStartup, MessageStrings.EnsureStartupClassExists));
                }
                _logger.LogMessage("Attempting to compile the application in memory with the added DbContext");
                CompileAndGetDbContextAndModelTypes(dbContextFullTypeName,
                                                    modelTypeSymbol.FullName,
                                                    c =>
                {
                    c = c.AddSyntaxTrees(dbContextSyntaxTree);
                    if (startUpEditResult.Edited)
                    {
                        c = c.ReplaceSyntaxTree(startUpEditResult.OldTree, startUpEditResult.NewTree);
                    }
                    return(c);
                },
                                                    out dbContextType,
                                                    out modelReflectionType);

                // Add file information
                dbContextSyntaxTree = dbContextSyntaxTree.WithFilePath(GetPathForNewContext(dbContextTemplateModel.DbContextTypeName));
            }
            else
            {
                var addResult = _dbContextEditorServices.AddModelToContext(dbContextSymbols.First(), modelTypeSymbol);
                if (addResult.Edited)
                {
                    state = ContextProcessingStatus.ContextEdited;
                    dbContextSyntaxTree = addResult.NewTree;
                    _logger.LogMessage("Attempting to compile the application in memory with the modified DbContext");
                    CompileAndGetDbContextAndModelTypes(dbContextFullTypeName,
                                                        modelTypeSymbol.FullName,
                                                        c =>
                    {
                        var oldTree = c.SyntaxTrees.FirstOrDefault(t => t.FilePath == addResult.OldTree.FilePath);
                        Debug.Assert(oldTree != null);
                        return(c.ReplaceSyntaxTree(oldTree, addResult.NewTree));
                    },
                                                        out dbContextType,
                                                        out modelReflectionType);
                }
                else
                {
                    _logger.LogMessage("Attempting to compile the application in memory");
                    CompileAndGetDbContextAndModelTypes(dbContextFullTypeName,
                                                        modelTypeSymbol.FullName,
                                                        c => { return(c); },
                                                        out dbContextType,
                                                        out modelReflectionType);

                    if (dbContextType == null)
                    {
                        throw new InvalidOperationException(string.Format(MessageStrings.DbContextTypeNotFound, dbContextFullTypeName));
                    }
                }
            }

            if (modelReflectionType == null)
            {
                throw new InvalidOperationException(string.Format(MessageStrings.ModelTypeNotFound, modelTypeSymbol.Name));
            }

            _logger.LogMessage("Attempting to figure out the EntityFramework metadata for the model and DbContext: " + modelTypeSymbol.Name);

            var metadata = GetModelMetadata(dbContextType, modelReflectionType, startupType);

            // Write the DbContext/Startup if getting the model metadata is successful
            if (dbContextSyntaxTree != null)
            {
                PersistSyntaxTree(dbContextSyntaxTree);
                if (state == ContextProcessingStatus.ContextAdded || state == ContextProcessingStatus.ContextAddedButRequiresConfig)
                {
                    _logger.LogMessage("Added DbContext : " + dbContextSyntaxTree.FilePath.Substring(_applicationInfo.ApplicationBasePath.Length));

                    if (state != ContextProcessingStatus.ContextAddedButRequiresConfig)
                    {
                        PersistSyntaxTree(startUpEditResult.NewTree);
                    }
                    else
                    {
                        _logger.LogMessage("However there may be additional steps required for the generted code to work properly, refer to documentation <forward_link>.");
                    }
                }
            }
            return(new ContextProcessingResult()
            {
                ContextProcessingStatus = state,
                ModelMetadata = metadata
            });
        }
コード例 #8
0
        public async Task <ModelMetadata> GetModelMetadata(string dbContextTypeName, ModelType modelTypeSymbol)
        {
            Type       dbContextType;
            var        dbContextSymbols = _modelTypesLocator.GetType(dbContextTypeName).ToList();
            var        isNewDbContext   = false;
            SyntaxTree newDbContextTree = null;
            NewDbContextTemplateModel dbContextTemplateModel = null;

            if (dbContextSymbols.Count == 0)
            {
                isNewDbContext = true;
                await ValidateEFSqlServerDependency();

                _logger.LogMessage("Generating a new DbContext class " + dbContextTypeName);
                dbContextTemplateModel = new NewDbContextTemplateModel(dbContextTypeName, modelTypeSymbol);
                newDbContextTree       = await _dbContextEditorServices.AddNewContext(dbContextTemplateModel);

                _logger.LogMessage("Attempting to compile the application in memory with the added DbContext");
                var projectCompilation = _libraryManager.GetProject(_environment).Compilation;
                var newAssemblyName    = projectCompilation.AssemblyName + _counter++;
                var newCompilation     = projectCompilation.AddSyntaxTrees(newDbContextTree).WithAssemblyName(newAssemblyName);

                var result = CommonUtilities.GetAssemblyFromCompilation(_loader, newCompilation);
                if (result.Success)
                {
                    dbContextType = result.Assembly.GetType(dbContextTypeName);
                    if (dbContextType == null)
                    {
                        throw new InvalidOperationException("There was an error creating a DbContext, there was no type returned after compiling the new assembly successfully");
                    }
                }
                else
                {
                    throw new InvalidOperationException("There was an error creating a DbContext :" + string.Join("\n", result.ErrorMessages));
                }
            }
            else
            {
                dbContextType = _libraryManager.GetReflectionType(_environment, dbContextTypeName);

                if (dbContextType == null)
                {
                    throw new InvalidOperationException("Could not get the reflection type for DbContext : " + dbContextTypeName);
                }
            }

            var modelTypeName = modelTypeSymbol.FullName;
            var modelType     = _libraryManager.GetReflectionType(_environment, modelTypeName);

            if (modelType == null)
            {
                throw new InvalidOperationException("Could not get the reflection type for Model : " + modelTypeName);
            }

            _logger.LogMessage("Attempting to figure out the EntityFramework metadata for the model and DbContext");
            var metadata = GetModelMetadata(dbContextType, modelType);

            // Write the DbContext if getting the model metadata is successful
            if (isNewDbContext)
            {
                await WriteDbContext(dbContextTemplateModel, newDbContextTree);
            }

            return(metadata);
        }
コード例 #9
0
        public async Task Process()
        {
            var dbContextSymbols = _modelTypesLocator.GetType(_dbContextFullTypeName).ToList();
            var startupType      = _modelTypesLocator.GetType("Startup").FirstOrDefault();
            var programType      = _modelTypesLocator.GetType("Program").FirstOrDefault();

            ModelType dbContextSymbolInWebProject = null;

            if (!dbContextSymbols.Any())
            {
                await GenerateNewDbContextAndRegister(startupType, programType);
            }
            else if (TryGetDbContextSymbolInWebProject(dbContextSymbols, out dbContextSymbolInWebProject))
            {
                await AddModelTypeToExistingDbContextIfNeeded(dbContextSymbolInWebProject);
            }
            else
            {
                await EnsureDbContextInLibraryIsValid(dbContextSymbols.First());
            }

            var dbContextType = _reflectedTypesProvider.GetReflectedType(
                modelType: _dbContextFullTypeName,
                lookInDependencies: true);

            if (dbContextType == null)
            {
                throw new InvalidOperationException(_dbContextError);
            }

            var modelReflectionType = _reflectedTypesProvider.GetReflectedType(
                modelType: _modelTypeSymbol.FullName,
                lookInDependencies: true);

            if (modelReflectionType == null)
            {
                throw new InvalidOperationException(string.Format(MessageStrings.ModelTypeNotFound, _modelTypeSymbol.Name));
            }

            var reflectedStartupType = _reflectedTypesProvider.GetReflectedType(
                modelType: startupType.FullName,
                lookInDependencies: true);

            if (reflectedStartupType == null)
            {
                throw new InvalidOperationException(string.Format(MessageStrings.ModelTypeNotFound, reflectedStartupType.Name));
            }

            _logger.LogMessage(string.Format(MessageStrings.GettingEFMetadata, _modelTypeSymbol.Name));

            ModelMetadata = GetModelMetadata(dbContextType, modelReflectionType, reflectedStartupType);

            if (_dbContextSyntaxTree != null)
            {
                PersistSyntaxTree(_dbContextSyntaxTree);

                if (ContextProcessingStatus == ContextProcessingStatus.ContextAdded || ContextProcessingStatus == ContextProcessingStatus.ContextAddedButRequiresConfig)
                {
                    _logger.LogMessage(string.Format(MessageStrings.AddedDbContext, _dbContextSyntaxTree.FilePath.Substring(_applicationInfo.ApplicationBasePath.Length)));

                    if (ContextProcessingStatus != ContextProcessingStatus.ContextAddedButRequiresConfig)
                    {
                        PersistSyntaxTree(_startupEditResult.NewTree);
                    }
                    else
                    {
                        _logger.LogMessage(MessageStrings.AdditionalSteps);
                    }
                }
            }
        }
コード例 #10
0
        public async Task <ContextProcessingResult> GetModelMetadata(string dbContextFullTypeName, ModelType modelTypeSymbol, string areaName)
        {
            Type       dbContextType;
            SyntaxTree dbContextSyntaxTree = null;

            EditSyntaxTreeResult startUpEditResult = new EditSyntaxTreeResult()
            {
                Edited = false
            };

            ContextProcessingStatus state = ContextProcessingStatus.ContextAvailable;

            var  dbContextSymbols    = _modelTypesLocator.GetType(dbContextFullTypeName).ToList();
            var  startupType         = _modelTypesLocator.GetType("Startup").FirstOrDefault();
            var  programType         = _modelTypesLocator.GetType("Program").FirstOrDefault();
            Type modelReflectionType = null;
            ReflectedTypesProvider reflectedTypesProvider = null;
            string dbContextError = string.Empty;

            AssemblyAttributeGenerator assemblyAttributeGenerator = GetAssemblyAttributeGenerator();

            if (dbContextSymbols.Count == 0)
            {
                ValidateEFSqlServerDependency();

                // Create a new Context
                _logger.LogMessage(string.Format(MessageStrings.GeneratingDbContext, dbContextFullTypeName));
                var dbContextTemplateModel = new NewDbContextTemplateModel(dbContextFullTypeName, modelTypeSymbol, programType);
                dbContextSyntaxTree = await _dbContextEditorServices.AddNewContext(dbContextTemplateModel);

                state = ContextProcessingStatus.ContextAdded;

                // Edit startup class to register the context using DI
                if (startupType != null)
                {
                    startUpEditResult = _dbContextEditorServices.EditStartupForNewContext(startupType,
                                                                                          dbContextTemplateModel.DbContextTypeName,
                                                                                          dbContextTemplateModel.DbContextNamespace,
                                                                                          dataBaseName: dbContextTemplateModel.DbContextTypeName + "-" + Guid.NewGuid().ToString());
                }

                if (!startUpEditResult.Edited)
                {
                    state = ContextProcessingStatus.ContextAddedButRequiresConfig;

                    // The created context would anyway fail to fetch metadata with a crypic message
                    // It's better to throw with a meaningful message
                    throw new InvalidOperationException(string.Format("{0} {1}", MessageStrings.FailedToEditStartup, MessageStrings.EnsureStartupClassExists));
                }
                _logger.LogMessage(MessageStrings.CompilingWithAddedDbContext);

                var projectCompilation = await _workspace.CurrentSolution.Projects
                                         .First(project => project.AssemblyName == _projectContext.AssemblyName)
                                         .GetCompilationAsync();

                reflectedTypesProvider = new ReflectedTypesProvider(
                    projectCompilation,
                    c =>
                {
                    c = c.AddSyntaxTrees(assemblyAttributeGenerator.GenerateAttributeSyntaxTree());
                    c = c.AddSyntaxTrees(dbContextSyntaxTree);
                    if (startUpEditResult.Edited)
                    {
                        c = c.ReplaceSyntaxTree(startUpEditResult.OldTree, startUpEditResult.NewTree);
                    }
                    return(c);
                },
                    _projectContext,
                    _loader,
                    _logger);

                var compilationErrors = reflectedTypesProvider.GetCompilationErrors();
                dbContextError = string.Format(
                    MessageStrings.DbContextCreationError,
                    (compilationErrors == null
                        ? string.Empty
                        : string.Join(Environment.NewLine, compilationErrors)));

                // Add file information
                dbContextSyntaxTree = dbContextSyntaxTree.WithFilePath(GetPathForNewContext(dbContextTemplateModel.DbContextTypeName, areaName));
            }
            else
            {
                var addResult          = _dbContextEditorServices.AddModelToContext(dbContextSymbols.First(), modelTypeSymbol);
                var projectCompilation = await _workspace.CurrentSolution.Projects
                                         .First(project => project.AssemblyName == _projectContext.AssemblyName)
                                         .GetCompilationAsync();

                if (addResult.Edited)
                {
                    state = ContextProcessingStatus.ContextEdited;
                    dbContextSyntaxTree = addResult.NewTree;
                    _logger.LogMessage(MessageStrings.CompilingWithModifiedDbContext);

                    reflectedTypesProvider = new ReflectedTypesProvider(
                        projectCompilation,
                        c =>
                    {
                        c           = c.AddSyntaxTrees(assemblyAttributeGenerator.GenerateAttributeSyntaxTree());
                        var oldTree = c.SyntaxTrees.FirstOrDefault(t => t.FilePath == addResult.OldTree.FilePath);
                        if (oldTree == null)
                        {
                            throw new InvalidOperationException(string.Format(
                                                                    MessageStrings.ModelTypeCouldNotBeAdded,
                                                                    modelTypeSymbol.FullName,
                                                                    dbContextFullTypeName));
                        }
                        return(c.ReplaceSyntaxTree(oldTree, addResult.NewTree));
                    },
                        _projectContext,
                        _loader,
                        _logger);

                    var compilationErrors = reflectedTypesProvider.GetCompilationErrors();
                    dbContextError = string.Format(
                        MessageStrings.DbContextCreationError,
                        (compilationErrors == null
                            ? string.Empty
                            : string.Join(Environment.NewLine, compilationErrors)));
                }
                else
                {
                    _logger.LogMessage(MessageStrings.CompilingInMemory);

                    reflectedTypesProvider = new ReflectedTypesProvider(
                        projectCompilation,
                        c =>
                    {
                        c = c.AddSyntaxTrees(assemblyAttributeGenerator.GenerateAttributeSyntaxTree());
                        return(c);
                    },
                        _projectContext,
                        _loader,
                        _logger);

                    dbContextError = string.Format(MessageStrings.DbContextTypeNotFound, dbContextFullTypeName);
                }
            }
            dbContextType = reflectedTypesProvider.GetReflectedType(
                modelType: dbContextFullTypeName,
                lookInDependencies: true);

            if (dbContextType == null)
            {
                throw new InvalidOperationException(dbContextError);
            }

            modelReflectionType = reflectedTypesProvider.GetReflectedType(
                modelType: modelTypeSymbol.FullName,
                lookInDependencies: true);
            if (modelReflectionType == null)
            {
                throw new InvalidOperationException(string.Format(MessageStrings.ModelTypeNotFound, modelTypeSymbol.Name));
            }

            var reflectedStartupType = reflectedTypesProvider.GetReflectedType(
                modelType: startupType.FullName,
                lookInDependencies: true);

            if (reflectedStartupType == null)
            {
                throw new InvalidOperationException(string.Format(MessageStrings.ModelTypeNotFound, reflectedStartupType.Name));
            }

            _logger.LogMessage(string.Format(MessageStrings.GettingEFMetadata, modelTypeSymbol.Name));

            var metadata = GetModelMetadata(dbContextType, modelReflectionType, reflectedStartupType);

            // Write the DbContext/Startup if getting the model metadata is successful
            if (dbContextSyntaxTree != null)
            {
                PersistSyntaxTree(dbContextSyntaxTree);

                if (state == ContextProcessingStatus.ContextAdded || state == ContextProcessingStatus.ContextAddedButRequiresConfig)
                {
                    _logger.LogMessage(string.Format(MessageStrings.AddedDbContext, dbContextSyntaxTree.FilePath.Substring(_applicationInfo.ApplicationBasePath.Length)));

                    if (state != ContextProcessingStatus.ContextAddedButRequiresConfig)
                    {
                        PersistSyntaxTree(startUpEditResult.NewTree);
                    }
                    else
                    {
                        _logger.LogMessage(MessageStrings.AdditionalSteps);
                    }
                }
            }
            return(new ContextProcessingResult()
            {
                ContextProcessingStatus = state,
                ModelMetadata = metadata
            });
        }