static void Main(string[] args) { // This section serves as the composition root. // In Dependency Injection or Inversion of Control, the composition root is the "entry" point of the application. // For web-applications it is the App_Start or AppStart, for windows services it is the OnStart method. // For console applications, it is the main method. // Only executables have a REAL composition root. Class libraries are by definition a library of types to be used by // calling code to accomplish a goal. The class library cannot (and should not) make any assumptions beyond it's own behavior // regarding how it will be used. // Take note of the difference between the IConfigurationProvider and the AppConfigProvider. // The interface is defined in the class library, while the implementation is defined in the console application project. // This setup allows the console application to be able to "read" configuration, without having to know how that particular configuration // should be accessed. You COULD provide a default provider in the class library for configuration (as we did with the FileSystem) // but this gives us maximum flexibility. This same class library used in a web.application would load config from a web.config // file instead of an app.config. Or it could be a SQLConfigurationProvider as long as they implement the class library interface. IConfigurationProvider provider = new AppConfigProvider(); IDataProcessor processor = new TextFileProcessor(); IFileSystemProvider fileSystem = new SimpleFileSystemProvider(); // Notice the .Out property of the static Console class being passed as an argument. // The constructor dependency for the ConsoleReportViewer requires a TextWriter instance (which the .Out property happens to be). // We could really pass in ANY TextWriter instance, so you COULD rename the ConsoleReportViewer to TextReportViewer to be more specific. // It is this injected dependency that allows us to // A) Actually test the output in tests // B) De-couple the ConsoleReportViewer from NEEDING to run in a place where it has access to the actual Console. // In this case, we don't have to worry about disposing of the TextWriter (like you would normally) because it's lifetime is managed // by the Console Application IReportViewer viewer = new ConsoleReportViewer(Console.Out); // Because we have modified the constructor to take interface arguments, and moved the primary logic from the actual viewer // to a new "layer" called an engine, our code-base has become larger, but also more loosely coupled. ReportingEngine engine = new ReportingEngine(provider, processor, fileSystem, viewer); engine.GenerateReport(); Console.ReadLine(); }
/// <summary> /// Generates the excel report and sends it in an email /// </summary> private void GenerateReport(string filename) { List <string> sessionIds = _scenarioList.Select(x => x.SessionId).ToList(); // Prompt the user for the report destination and create the report string fileSession = (sessionIds.Count() == 1 ? sessionIds.First() : "Multiple Sessions"); string reportName = Path.GetFileNameWithoutExtension(ReportTemplateFileName); if (string.IsNullOrEmpty(filename)) { SaveFileDialog saveFileDialog = new SaveFileDialog { DefaultExt = "xlsx", Filter = "Excel Documents (*.xlsx)|*.xlsx", FileName = "{0} {1} {2}".FormatWith(DateTime.Today.ToString("MMM dd", CultureInfo.CurrentCulture), fileSession, reportName), InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) }; if (saveFileDialog.ShowDialog() == true) { filename = saveFileDialog.FileName; } } else { filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), filename); } if (string.IsNullOrEmpty(filename)) { return; } try { _destinationReportFileName = filename; ReportingEngine.GenerateReport(ReportTemplateFileName, filename, sessionIds); EmailTestResult(); // Copy the template to the destination _destinationReportFileName = filename; File.Copy(ReportTemplateFileName, _destinationReportFileName, true); // Create the report //_excelReport = new ExcelReportFile(_destinationReportFileName); // //Thread the report creation // BackgroundWorker generateReportWorker = new BackgroundWorker(); // generateReportWorker.DoWork += generateReportWorker_DoWork; // generateReportWorker.RunWorkerCompleted += generateReportWorker_RunWorkerCompleted; // generateReportWorker.RunWorkerAsync(new object[] { _excelReport, sessionIds, DataLogSqlConnection.ConnectionString }); } catch (Exception ex) { MessageBox.Show(ex.Message, "Report Creation Failure", MessageBoxButton.OK, MessageBoxImage.Error); TraceFactory.Logger.Error(ex.Message, ex); } }