public async Task <ContextProcessingResult> GetModelMetadata(ModelType modelType)
        {
            if (modelType == null)
            {
                throw new ArgumentNullException(nameof(modelType));
            }

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

            var reflectedTypesProvider = new ReflectedTypesProvider(
                projectCompilation,
                (c) => c,
                _projectContext,
                _loader,
                _logger);
            var modelReflectionType = reflectedTypesProvider.GetReflectedType(
                modelType: modelType.FullName,
                lookInDependencies: true);

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

            var modelMetadata = new CodeModelMetadata(modelReflectionType);

            return(new ContextProcessingResult()
            {
                ContextProcessingStatus = ContextProcessingStatus.ContextAvailable,
                ModelMetadata = modelMetadata
            });
        }
        private async Task EnsureDbContextInLibraryIsValid(ModelType dbContextSymbol)
        {
            var projectCompilation = await _workspace.CurrentSolution.Projects
                                     .First(project => project.AssemblyName == _projectContext.AssemblyName)
                                     .GetCompilationAsync();

            _reflectedTypesProvider = GetReflectedTypesProvider(
                projectCompilation,
                c =>
            {
                c = c.AddSyntaxTrees(_assemblyAttributeGenerator.GenerateAttributeSyntaxTree());
                return(c);
            });

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

            if (_reflectedTypesProvider.GetCompilationErrors() != null &&
                _reflectedTypesProvider.GetCompilationErrors().Any())
            {
                throw new InvalidOperationException(string.Format(
                                                        MessageStrings.FailedToCompileInMemory,
                                                        string.Join(Environment.NewLine, _reflectedTypesProvider.GetCompilationErrors())
                                                        ));
            }

            var props = dbContextType.GetProperties()
                        .Where(p => p.PropertyType.IsGenericType &&
                               p.PropertyType.GenericTypeArguments.Any() &&
                               p.PropertyType.Name.Equals("DbSet`1") &&
                               p.PropertyType.Namespace.Equals("Microsoft.EntityFrameworkCore"));

            if (!props.Any(p => p.PropertyType.GenericTypeArguments[0].FullName.Equals(_modelTypeSymbol.FullName)))
            {
                throw new InvalidOperationException(string.Format(
                                                        MessageStrings.ModelTypeCouldNotBeAdded,
                                                        _modelTypeSymbol.FullName,
                                                        _dbContextFullTypeName));
            }
        }
        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);
                    }
                }
            }
        }