Beispiel #1
0
        private int Scaffold(
            ScaffoldOptions settings,
            ScaffoldInterceptors?interceptors,
            string provider,
            string?providerLocation,
            string connectionString,
            string?additionalConnectionString,
            string output,
            bool overwrite)
        {
            using var dc  = GetConnection(provider, providerLocation, connectionString, additionalConnectionString, out var secondaryConnection);
            using var sdc = secondaryConnection;
            if (dc == null)
            {
                return(StatusCodes.EXPECTED_ERROR);
            }

            var language = LanguageProviders.CSharp;

            var                  legacyProvider       = new LegacySchemaProvider(dc, settings.Schema, language);
            ISchemaProvider      schemaProvider       = legacyProvider;
            ITypeMappingProvider typeMappingsProvider = legacyProvider;

            if (sdc != null)
            {
                var secondLegacyProvider = new LegacySchemaProvider(sdc, settings.Schema, language);
                schemaProvider       = new MergedAccessSchemaProvider(legacyProvider, secondLegacyProvider);
                typeMappingsProvider = new AggregateTypeMappingsProvider(legacyProvider, secondLegacyProvider);
            }

            var generator  = new Scaffolder(LanguageProviders.CSharp, HumanizerNameConverter.Instance, settings, interceptors);
            var dataModel  = generator.LoadDataModel(schemaProvider, typeMappingsProvider);
            var sqlBuilder = dc.DataProvider.CreateSqlBuilder(dc.MappingSchema);
            var files      = generator.GenerateCodeModel(
                sqlBuilder,
                dataModel,
                MetadataBuilders.GetAttributeBasedMetadataBuilder(generator.Language, sqlBuilder),
                SqlBoolEqualityConverter.Create(generator.Language));
            var sourceCode = generator.GenerateSourceCode(files);

            Directory.CreateDirectory(output);

            for (var i = 0; i < sourceCode.Length; i++)
            {
                // TODO: add file name normalization/deduplication?
                var fileName = Path.Combine(output, sourceCode[i].FileName);
                if (File.Exists(fileName) && !overwrite)
                {
                    Console.WriteLine($"File '{fileName}' already exists. Specify '--overwrite true' option if you want to ovrerwrite existing files");
                    return(StatusCodes.EXPECTED_ERROR);
                }

                File.WriteAllText(fileName, sourceCode[i].Code);
            }

            return(StatusCodes.SUCCESS);
        }
Beispiel #2
0
        /// <summary>
        /// Configure scaffolder options object.
        /// </summary>
        /// <param name="options">CLI options.</param>
        /// <returns>Scaffold settings or <c>null</c> on error.</returns>
        private static ScaffoldOptions?ProcessScaffoldOptions(Dictionary <CliOption, object?> options)
        {
            ScaffoldOptions settings;

            // before reading other options load base settings object
            if (options.Remove(General.OptionsTemplate, out var value) && value is "t4")
            {
                settings = ScaffoldOptions.T4();
            }
            else
            {
                settings = ScaffoldOptions.Default();
            }

            // process scaffold options
            ProcessSchemaOptions(options, settings.Schema);
            ProcessDataModelOptions(options, settings.DataModel);
            ProcessCodeGenOptions(options, settings.CodeGeneration);

            return(settings);
        }
Beispiel #3
0
        /// <summary>
        /// Loads interceptors from assembly from specified path.
        /// </summary>
        /// <param name="assemblyPath">Path to assembly with interceptors.</param>
        /// <returns>Status of operation and loaded interceptors (on failure).</returns>
        private (int resultCode, ScaffoldInterceptors?interceptors) LoadInterceptorsFromAssembly(string assemblyPath, ScaffoldOptions options)
        {
            // as loaded assembly could have additional sideload references, we should try to handle them
            var assemblyFolder = Path.GetDirectoryName(Path.GetFullPath(assemblyPath)) !;

            // try to load side-assemblies from same folder
            // TODO: Verbose logging
            Console.WriteLine($"AssemblyResolve path: {assemblyFolder}");

            Assembly assembly;

            try
            {
                assembly = Assembly.LoadFrom(assemblyPath);
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"Failed to load assembly with interceptors from '{assemblyPath}': {ex}");
                return(StatusCodes.INVALID_ARGUMENTS, null);
            }

            SetupInterceptorsDependencyResolver(assemblyFolder, assembly);

            return(LoadInterceptorsFromAssembly(assemblyPath, assembly, options));
        }
Beispiel #4
0
        /// <summary>
        /// Load interceptors from file at provided path. It could be assembly with interceptors if path must ends with .dll extension
        /// or T4 template otherwise.
        /// </summary>
        /// <param name="interceptorsPath">Path to interceptors file.</param>
        /// <returns>Method execution status and interceptors instance on success.</returns>
        private (int resultCode, ScaffoldInterceptors?interceptors) LoadInterceptors(string interceptorsPath, ScaffoldOptions options)
        {
            if (Path.GetExtension(interceptorsPath).Equals(".dll", StringComparison.OrdinalIgnoreCase))
            {
                return(LoadInterceptorsFromAssembly(interceptorsPath, options));
            }

            return(LoadInterceptorsFromT4(interceptorsPath, options));
        }
Beispiel #5
0
        /// <summary>
        /// Compile and execute T4 template, provided by user.
        /// </summary>
        /// <param name="t4templatePath">Path to T4 template.</param>
        /// <returns>Template processing status and interceptors instance on success.</returns>
        private (int resultCode, ScaffoldInterceptors?interceptors) LoadInterceptorsFromT4(string t4templatePath, ScaffoldOptions options)
        {
            // load template source and assembly references from T4 file
            var status = PreprocessTemplate(t4templatePath, out var refs, out var templateCode, out var imports);

            if (status != StatusCodes.SUCCESS)
            {
                return(status, null);
            }

            // compile template and load interceptors assembly
            (status, var assembly) = CompileTemplateAndLoadAssembly(templateCode, refs, imports);
            if (status != StatusCodes.SUCCESS)
            {
                return(status, null);
            }

            // instantiate interceptors instance
            return(LoadInterceptorsFromAssembly(t4templatePath, assembly !, options));
        }
Beispiel #6
0
        /// <summary>
        /// Locate and create instance of interceptors from <paramref name="assembly"/>.
        /// </summary>
        /// <param name="sourcePath">Interceptors source path (T4 template path or assembly path) for logging purposes.</param>
        /// <param name="assembly">Assembly with interceptors class.</param>
        /// <returns>Method execution status and interceptors instance on success.</returns>
        private static (int resultCode, ScaffoldInterceptors?interceptors) LoadInterceptorsFromAssembly(string sourcePath, Assembly assembly, ScaffoldOptions options)
        {
            Type?interceptorsType = null;

            foreach (var type in assembly.GetTypes())
            {
                if (Inherits(type, typeof(ScaffoldInterceptors)))
                {
                    // only one interceptors class allowed
                    if (interceptorsType != null)
                    {
                        Console.Error.WriteLine($"'{sourcePath}' contains multiple interceptor types: {interceptorsType}, {interceptorsType}");
                        return(StatusCodes.EXPECTED_ERROR, null);
                    }

                    interceptorsType = type;
                }
            }

            // interceptors class not found?
            if (interceptorsType == null)
            {
                Console.Error.WriteLine($"Cannot find interceptor class in '{sourcePath}'");
                return(StatusCodes.EXPECTED_ERROR, null);
            }

            // try options constructor first
            object[]? args = null;
            var ctor = interceptorsType.GetConstructor(new[] { typeof(ScaffoldOptions) });

            if (ctor == null)
            {
                // try default constructor
                ctor = interceptorsType.GetConstructor(Array.Empty <Type>());
            }
            else
            {
                args = new[] { options };
            }

            if (ctor == null)
            {
                Console.Error.WriteLine($"Interceptor class '{interceptorsType}' missing default constrtuctor");
                return(StatusCodes.EXPECTED_ERROR, null);
            }

            try
            {
                return(StatusCodes.SUCCESS, (ScaffoldInterceptors)Activator.CreateInstance(interceptorsType, args) !);
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"Failed to create instance of interceptor '{interceptorsType}': {ex}");
                return(StatusCodes.EXPECTED_ERROR, null);
            }
        }