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()); }
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(); }
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); } }
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); } }
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); }
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()); }
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 }); }
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); }
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); } } } }
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 }); }