public void Execute(Processor processor, ProcessorParameters parameters) { if (processor.CancelToken.IsCancellationRequested) { return; } processor.PublishProcessMessage("Loading T4 Template Definitions..."); IList <ITemplateDefinition> definitions = null; try { definitions = TemplateDefinitionHelper.GetDefinitions(); } catch (Exception x) { processor.PublishErrorMessage("Failed while loading T4 Template Definitions -> {0}", x.Message); return; } processor.PublishMessage("{0} T4 Template Definitions loaded.", definitions.Count); #region [ Computing the number of files to create ] int totalFileNumber = 0; int currentFileNumber = 0; foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByTable)) { foreach (var table in processor.ModelDescriptor.Schema.Tables.Where( i => parameters.TableNames.Contains(i.Name, new StringIgnoreCaseEqualityComparer()))) { totalFileNumber++; } } foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByBusiness)) { foreach (var bcInfo in processor.BusinessContext.BusinessClasses) { totalFileNumber++; } } foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.Normal)) { totalFileNumber++; } #endregion processor.PublishProcessMessage("Executing T4 Templates..."); #region [ OneByTable Section ] foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByTable)) { foreach (var table in processor.ModelDescriptor.Schema.Tables.Where( i => parameters.TableNames.Contains(i.Name, new StringIgnoreCaseEqualityComparer()))) { if (processor.CancelToken.IsCancellationRequested) { return; } processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber); if (definition.CanBeExecuted(processor.Context, table)) { string t4Template = processor.GetTemplateFilePathToProcess(definition); string outputFilePath = processor.GetOutputFilePathToCreate(definition, table.Name); if (!definition.OverrideFileIfExists && File.Exists(outputFilePath)) { continue; } processor.PublishProcessMessage("Processing {0} (Table = {1})...", definition.TemplatePath, table.Name); var p = new Dictionary <string, object>(); p.Add("Context", new TextTemplatingProcessContext { ProcessorContext = processor.Context, Schema = processor.ModelDescriptor.Schema, Table = table, BusinessClass = processor.BusinessContext.GetBusinessClass(table.Name) }); definition.AddParameters(processor.Context, p); processor.TextTemplatingEngine.SetParameters(p); processor.Process(t4Template, outputFilePath, definition, parameters); } } } #endregion #region [ OneByBusiness Section ] foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByBusiness)) { foreach (BusinessClassInfo bcInfo in processor.BusinessContext.BusinessClasses) { if (processor.CancelToken.IsCancellationRequested) { return; } processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber); if (definition.CanBeExecuted(processor.Context, new object[] { processor.ModelDescriptor, bcInfo.Name })) { string t4Template = processor.GetTemplateFilePathToProcess(definition); string outputFilePath = processor.GetOutputFilePathToCreate(definition, bcInfo.Name); if (!definition.OverrideFileIfExists && File.Exists(outputFilePath)) { continue; } processor.PublishProcessMessage("Processing {0} (Business = {1})...", definition.TemplatePath, bcInfo.Name); var p = new Dictionary <string, object>(); p.Add("Context", new TextTemplatingProcessContext { ProcessorContext = processor.Context, Schema = processor.ModelDescriptor.Schema, Table = new ModelDescriptorSchemaTable { Name = bcInfo.Name }, BusinessClass = processor.BusinessContext.GetBusinessClass(bcInfo.Name) }); definition.AddParameters(processor.Context, p); processor.TextTemplatingEngine.SetParameters(p); processor.Process(t4Template, outputFilePath, definition, parameters); } } } #endregion #region [ Normal Section ] foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.Normal)) { if (processor.CancelToken.IsCancellationRequested) { return; } processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber); if (definition.CanBeExecuted(processor.Context)) { string t4Template = processor.GetTemplateFilePathToProcess(definition); string outputFilePath = processor.GetOutputFilePathToCreate(definition); if (!definition.OverrideFileIfExists && File.Exists(outputFilePath)) { continue; } processor.PublishProcessMessage("Processing {0}...", definition.TemplatePath); var p = new Dictionary <string, object>(); p.Add("Context", new TextTemplatingProcessContext { ProcessorContext = processor.Context, SmoContext = processor.SmoContext, Schema = processor.ModelDescriptor.Schema, BusinessClasses = processor.BusinessContext.BusinessClasses }); definition.AddParameters(processor.Context, p); processor.TextTemplatingEngine.SetParameters(p); processor.Process(t4Template, outputFilePath, definition, parameters); } } #endregion }
public void Execute(Processor processor, ProcessorParameters parameters) { IList <ITemplateDefinition> definitions = new List <ITemplateDefinition> { new TemplateDefinitions.Models.EntityGeneratedCsTemplateDefinition(), }; #region [ Computing the number of files to create ] int totalFileNumber = 0; int currentFileNumber = 0; foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByTable)) { foreach (var table in processor.ModelDescriptor.Schema.Tables /* All tables */) { totalFileNumber++; } } #endregion foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByTable)) { foreach (var table in processor.ModelDescriptor.Schema.Tables /* All tables */) { if (processor.CancelToken.IsCancellationRequested) { return; } processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber); if (definition.CanBeExecuted(processor.Context, table)) { string t4Template = processor.GetTemplateFilePathToProcess(definition); string outputFilePath = processor.GetOutputFilePathToCreate(definition, table.Name); if (!definition.OverrideFileIfExists && File.Exists(outputFilePath)) { continue; } processor.PublishProcessMessage("Processing {0} (Table = {1})...", definition.TemplatePath, table.Name); var p = new Dictionary <string, object>(); p.Add("Context", new TextTemplatingProcessContext { ProcessorContext = processor.Context, Schema = processor.ModelDescriptor.Schema, Table = table }); definition.AddParameters(processor.Context, p); processor.TextTemplatingEngine.SetParameters(p); processor.Process(t4Template, outputFilePath, definition, parameters); } } } }
internal void Process(string t4Template, string outputFilePath, ITemplateDefinition definition, ProcessorParameters parameters) { var ttParams = new TextTemplatingParameters( t4Template, outputFilePath, definition.OverrideFileIfExists, definition.AddToProject); string tmpOutputFilePath; try { var state = this.TextTemplatingEngine.Process(ttParams, out tmpOutputFilePath); if (state == ProcessStateEnum.Processed) { // SQL scripts... if (definition.ExecuteSqlScript) { bool canExecuted = true; if (definition is TemplateDefinitions.Database.InsertAllStoredProceduresGeneratedSqlTemplateDefinition && !parameters.WithSqlProcedureIntegration) { canExecuted = false; } if (canExecuted) { this.PublishProcessMessage("Executing {0}...", Path.GetFileName(tmpOutputFilePath)); try { SmoHelper.RunSqlScript(tmpOutputFilePath, this.SmoContext); } catch { // Create a copy of the tmpOutputFilePath file (for debug) because it will be deleted at the end of the whole process... FileHelper.TryCopy(tmpOutputFilePath, string.Concat(tmpOutputFilePath, ".err"), withOverwrite: true); throw; } } } } this.HasErrors |= state == ProcessStateEnum.Failed; } catch (Exception x) { this.PublishErrorMessage("Failed while processing {0} -> {1}", Path.GetFileName(t4Template), x.Message); } foreach (CompilerError error in this.TextTemplatingEngine.Errors) { this.PublishErrorMessage( "Template error: {0}({1},{2}): error {3}: {4}", Path.GetFileName(this.TextTemplatingEngine.Errors.First().FileName), error.Line, error.Column, error.ErrorNumber, error.ErrorText); } }
public void Execute(Processor processor, ProcessorParameters parameters) { IList <ITemplateDefinition> definitions = new List <ITemplateDefinition> { new TemplateDefinitions.Database.TranslationInitializationGeneratedSqlTemplateDefinition(), // Must be the first one! new TemplateDefinitions.Core.TranslationEnumGeneratedCsTemplateDefinition() }; #region [ Computing the number of files to create ] int totalFileNumber = 0; int currentFileNumber = 0; foreach (var definition in definitions) { totalFileNumber++; } #endregion foreach (var definition in definitions) { if (processor.CancelToken.IsCancellationRequested) { return; } processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber); if (definition.CanBeExecuted(processor.Context)) { string t4Template = processor.GetTemplateFilePathToProcess(definition); string outputFilePath = processor.GetOutputFilePathToCreate(definition); if (!definition.OverrideFileIfExists && File.Exists(outputFilePath)) { continue; } processor.PublishProcessMessage("Processing {0}...", definition.TemplatePath); var p = new Dictionary <string, object>(); p.Add("Context", new TextTemplatingProcessContext { ProcessorContext = processor.Context, SmoContext = processor.SmoContext, Schema = processor.ModelDescriptor.Schema }); definition.AddParameters(processor.Context, p); processor.TextTemplatingEngine.SetParameters(p); processor.Process(t4Template, outputFilePath, definition, new ProcessorParameters { WithSqlProcedureIntegration = true, // Always execute *.generated.sql files, CompilationMode = parameters.CompilationMode }); } } }
public void Execute(IProcessorBehavior behavior, ProcessorParameters parameters) { if (this.IsRunning) { ThrowException.Throw("The processor is already running"); } do { #region [ Begin ] this.IsRunning = true; _stopwatch = new Stopwatch(); _stopwatch.Start(); if (this.CancelToken != null) { this.CancelToken.Dispose(); } this.CancelToken = new CancellationTokenSource(); this.GeneratedServices = new List <string>(); this.HasErrors = false; this.PublishProcessMessage("Running Process ({0} mode)...", parameters.CompilationMode); #endregion #region [ Checking Assemblies Dependencies ] if (this.CancelToken.IsCancellationRequested) { break; } this.PublishProcessMessage("Checking Assemblies Dependencies..."); bool bOk = true; string modelAssemblyPath = Path.Combine(this.Context.SrcDirectory, string.Format(@"{0}.Models", this.Context.ProjectName), string.Format(@"bin\{0}", parameters.CompilationMode), string.Format(@"{0}.Models.dll", this.Context.ProjectName)); if (!File.Exists(modelAssemblyPath)) { bOk = false; } if (bOk) { string businessAssemblyPath = Path.Combine(this.Context.SrcDirectory, string.Format(@"{0}.Business", this.Context.ProjectName), string.Format(@"bin\{0}", parameters.CompilationMode), string.Format(@"{0}.Business.dll", this.Context.ProjectName)); if (!File.Exists(businessAssemblyPath)) { bOk = false; } } if (!bOk) { this.PublishErrorMessage( "The whole solution must be compiled ({0} mode) before running the proccess.", parameters.CompilationMode); break; } #endregion #region [ Checking and Loading Culture Context ] if (this.CancelToken.IsCancellationRequested) { break; } this.PublishProcessMessage("Checking and Loading Culture Context..."); string[] supportedCultures = DatabaseHelper.GetCultures(this.SmoContext); this.Context.Culture.SupportedCultures = supportedCultures; if (this.Context.Culture.SupportedCultures.Length == 0) { this.PublishErrorMessage("The 'Translation' table must define at least one culture!"); break; } foreach (string culture in supportedCultures.Where(c => c.Length != 2)) { this.PublishErrorMessage( "The '{0}' culture column from the 'Translation' table is not correct! Culture columns must be 2 characters long.", culture); break; } if (!supportedCultures.Contains(this.Context.Culture.Default)) { this.PublishErrorMessage( "The default culture '{0}' is not supported ({1}).", this.Context.Culture.Default, string.Join(", ", supportedCultures)); break; } #endregion #region [ Checking and Loading Database Structure ] if (this.CancelToken.IsCancellationRequested) { break; } this.PublishProcessMessage("Checking and Loading Database Structure..."); this.ModelDescriptor = new ModelDescriptor(this.SmoContext, this.Context); string mdFile = null; try { mdFile = this.ModelDescriptor.Load(this.CancelToken.Token); } catch (Exception x) { this.PublishErrorMessage( "Failed while loading Database Structure (Table: '{1}' - Column: '{2}') -> {0}", x, this.ModelDescriptor.CurrentTable.Name, this.ModelDescriptor.CurrentColumn.Name); break; } if (this.CancelToken.IsCancellationRequested) { break; } if (this.ModelDescriptor.Errors.Count != 0) { foreach (var error in this.ModelDescriptor.Errors) { this.PublishErrorMessage(error.GetError()); } break; } #endregion #region [ Checking Authentication Support ] if (this.CancelToken.IsCancellationRequested) { break; } var userTable = this.ModelDescriptor.Schema.Tables.FirstOrDefault(t => t.Name == this.Context.AuthenticationSupport.UserTableName); if (userTable == null) { this.PublishErrorMessage( "The '{0}' table declared in Context.AuthenticationSupport.UserTableName cannot be found in the database!", this.Context.AuthenticationSupport.UserTableName); break; } else { if (userTable.Columns.Count(c => c.Name == this.Context.AuthenticationSupport.UserTableIdentifiedColumnName) == 0) { this.PublishErrorMessage( "The '{0}' table must have a column named '{1}'!", this.Context.AuthenticationSupport.UserTableName, this.Context.AuthenticationSupport.UserTableIdentifiedColumnName); break; } // UserTableIdentifiedColumnName must have an UNIQUE constraint... if (userTable.Constraints == null || userTable.Constraints.Count(c => c.Columns.Any(i => i.Name == this.Context.AuthenticationSupport.UserTableIdentifiedColumnName)) == 0) { this.PublishErrorMessage( "The '{0}' column from the '{1}' table must have an UNIQUE constraint in order to be used as identifier column!", this.Context.AuthenticationSupport.UserTableIdentifiedColumnName, this.Context.AuthenticationSupport.UserTableName); break; } // UserTableName must define Password & Culture columns if (userTable.Columns.Count(c => c.CSharpPropertyName == "Password") == 0 || userTable.Columns.Count(c => c.CSharpPropertyName == "Culture") == 0) { this.PublishErrorMessage( "The '{0}' table must have '{0}_Password' and '{0}_Culture' columns!", this.Context.AuthenticationSupport.UserTableName); break; } } #endregion #region [ Loading Assemblies Dependencies ] if (this.CancelToken.IsCancellationRequested) { break; } this.PublishProcessMessage("Loading Assemblies Dependencies..."); Assembly businessAssembly = null; try { string tmpDir = Path.Combine(Path.GetTempPath(), "LayerCake Generator", this.Context.ProjectName); if (!Directory.Exists(tmpDir)) { Directory.CreateDirectory(tmpDir); } foreach (FileInfo file in new DirectoryInfo(tmpDir).GetFiles()) { string extension = file.Extension.ToLowerInvariant(); if (extension == ".dll" || extension == ".pdb") { try { file.Delete(); } catch (UnauthorizedAccessException) { // Occurred when the assembly is already loaded in the AppDomain.CurrentDomain } catch (Exception) { } } } string guid = Guid.NewGuid().ToString(); string assemblyPath = Path.GetDirectoryName( this.Context.GetAssemblyPath("Business", parameters.CompilationMode)); if (!Directory.Exists(assemblyPath)) { this.PublishErrorMessage("Cannot locate the path {0}", assemblyPath); break; } string businessAssemblyPath = null; ProxyDomain proxyDomain = new ProxyDomain(); // Copy all DLL/PDB files from the Business\bin\Debug to the Temp... foreach (FileInfo file in new DirectoryInfo(assemblyPath).GetFiles()) { string extension = file.Extension.ToLowerInvariant(); if (extension == ".dll" || extension == ".pdb") { string copiedDllPath = Path.Combine(tmpDir, string.Format("{0}.{1}{2}", Path.GetFileNameWithoutExtension(file.Name), guid, extension)); File.Copy(file.FullName, copiedDllPath); if (copiedDllPath.Contains(".Business") && Path.GetExtension(copiedDllPath).ToLowerInvariant() == ".dll") { businessAssemblyPath = copiedDllPath; } } } // Must be at the end once all the DLLs have been copied. // (cf. AppDomain Assembly Resolving (Program.cs, CurrentDomain_AssemblyResolve))... businessAssembly = proxyDomain.LoadAssembly(businessAssemblyPath); } catch (Exception x) { this.PublishErrorMessage( "Cannot load Assemblies Dependencies -> {0}", x.GetFullMessage(withExceptionType: true)); break; } #endregion #region [ Loading Business Context ] if (this.CancelToken.IsCancellationRequested) { break; } this.PublishProcessMessage("Loading Business Context..."); IList <string> errors; this.BusinessContext = new BusinessContext(businessAssembly); try { this.BusinessContext.Load(out errors); } catch (Exception x) { this.PublishErrorMessage("Cannot load the Business Context -> {0}", x.Message); break; } if (errors.Count != 0) { foreach (string error in errors) { this.PublishErrorMessage(error); } break; } #endregion #region [ Creating TextTemplating TextTemplatingEngine ] if (this.CancelToken.IsCancellationRequested) { break; } this.PublishProcessMessage("Creating TextTemplating Engine..."); this.TextTemplatingEngine = new TextTemplatingEngine( this.Context.SolutionDirectory, this.Context.TemplateDirectory); this.TextTemplatingEngine.OnGeneratedFile += OnFileGenerated; #endregion #region [ Executing... ] behavior.Execute(this, parameters); #endregion }while (false); #region [ End ] _stopwatch.Stop(); int nbFiles = this.TextTemplatingEngine != null?this.TextTemplatingEngine.GeneratedFiles.Count() : 0; string summary = string.Format("Process Duration -> {0}secs ({1} files)", (int)_stopwatch.Elapsed.TotalSeconds, nbFiles); if (this.HasErrors) { this.PublishErrorMessage("Undo code modifications"); this.PublishErrorMessage(summary); } else { if (this.CancelToken.IsCancellationRequested) // the process has been stopped -> do not commit (-> do not call LinkGeneratedFiles()) { this.PublishErrorMessage("Undo code modifications"); // cancel user action } else { this.LinkGeneratedFiles(); } this.PublishProcessMessage(summary); } this.Clear(); this.IsRunning = false; #endregion }