public EditSyntaxTreeResult AddModelToContext(ModelType dbContext, ModelType modelType) { if (!IsModelPropertyExists(dbContext.TypeSymbol, modelType.FullName)) { // Todo : Consider using DeclaringSyntaxtReference var sourceLocation = dbContext.TypeSymbol.Locations.Where(l => l.IsInSource).FirstOrDefault(); if (sourceLocation != null) { var syntaxTree = sourceLocation.SourceTree; var rootNode = syntaxTree.GetRoot(); var dbContextNode = rootNode.FindNode(sourceLocation.SourceSpan); var lastNode = dbContextNode.ChildNodes().Last(); var safeModelName = GetSafeModelName(modelType.Name, dbContext.TypeSymbol); // Todo : Need pluralization for property name below. // It is not always safe to just use DbSet<modelType.Name> as there can be multiple class names in different namespaces. var dbSetProperty = "public DbSet<" + modelType.FullName + "> " + safeModelName + " { get; set; }" + Environment.NewLine; var propertyDeclarationWrapper = CSharpSyntaxTree.ParseText(dbSetProperty); var newNode = rootNode.InsertNodesAfter(lastNode, propertyDeclarationWrapper.GetRoot().WithTriviaFrom(lastNode).ChildNodes()); newNode = RoslynCodeEditUtilities.AddUsingDirectiveIfNeeded("Microsoft.EntityFrameworkCore", newNode as CompilationUnitSyntax); //DbSet namespace newNode = RoslynCodeEditUtilities.AddUsingDirectiveIfNeeded(modelType.Namespace, newNode as CompilationUnitSyntax); var modifiedTree = syntaxTree.WithRootAndOptions(newNode, syntaxTree.Options); return(new EditSyntaxTreeResult() { Edited = true, OldTree = syntaxTree, NewTree = modifiedTree }); } } return(new EditSyntaxTreeResult() { Edited = false }); }
public EditSyntaxTreeResult EditStartupForNewContext(ModelType startUp, string dbContextTypeName, string dbContextNamespace, string dataBaseName) { Contract.Assert(startUp != null && startUp.TypeSymbol != null); Contract.Assert(!String.IsNullOrEmpty(dbContextTypeName)); Contract.Assert(!String.IsNullOrEmpty(dataBaseName)); var declarationReference = startUp.TypeSymbol.DeclaringSyntaxReferences.FirstOrDefault(); if (declarationReference != null) { var sourceTree = declarationReference.SyntaxTree; var rootNode = sourceTree.GetRoot(); var startUpClassNode = rootNode.FindNode(declarationReference.Span); var configServicesMethod = startUpClassNode.ChildNodes() .FirstOrDefault(n => n is MethodDeclarationSyntax && ((MethodDeclarationSyntax)n).Identifier.ToString() == "ConfigureServices") as MethodDeclarationSyntax; var configRootProperty = TryGetIConfigurationRootProperty(startUp.TypeSymbol); if (configServicesMethod != null && configRootProperty != null) { var servicesParam = configServicesMethod.ParameterList.Parameters .FirstOrDefault(p => p.Type.ToString() == "IServiceCollection") as ParameterSyntax; if (servicesParam != null) { AddConnectionString(dbContextTypeName, dataBaseName); var statementLeadingTrivia = configServicesMethod.Body.OpenBraceToken.LeadingTrivia.ToString() + " "; string textToAddAtEnd = statementLeadingTrivia + "{0}.AddDbContext<{1}>(options =>" + Environment.NewLine + statementLeadingTrivia + " options.UseSqlServer({2}.GetConnectionString(\"{1}\")));" + Environment.NewLine; if (configServicesMethod.Body.Statements.Any()) { textToAddAtEnd = Environment.NewLine + textToAddAtEnd; } var expression = SyntaxFactory.ParseStatement(String.Format(textToAddAtEnd, servicesParam.Identifier, dbContextTypeName, configRootProperty.Name)); MethodDeclarationSyntax newConfigServicesMethod = configServicesMethod.AddBodyStatements(expression); var newRoot = rootNode.ReplaceNode(configServicesMethod, newConfigServicesMethod); var namespacesToAdd = new[] { "Microsoft.EntityFrameworkCore", "Microsoft.Extensions.DependencyInjection", dbContextNamespace }; foreach (var namespaceName in namespacesToAdd) { newRoot = RoslynCodeEditUtilities.AddUsingDirectiveIfNeeded(namespaceName, newRoot as CompilationUnitSyntax); } return(new EditSyntaxTreeResult() { Edited = true, OldTree = sourceTree, NewTree = sourceTree.WithRootAndOptions(newRoot, sourceTree.Options) }); } } } return(new EditSyntaxTreeResult() { Edited = false }); }