CSVPosterEngine.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. using CsvHelper;
  2. using InABox.Core;
  3. using InABox.Core.Postable;
  4. using InABox.Scripting;
  5. using Microsoft.Win32;
  6. using System.Collections.Generic;
  7. using System.Globalization;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. namespace InABox.Poster.CSV;
  13. public class CSVPosterEngine<TPostable> : PosterEngine<TPostable, ICSVPoster<TPostable>, CSVPosterSettings>
  14. where TPostable : Entity, IPostable, IRemotable, IPersistent, new()
  15. {
  16. private ScriptDocument? _script;
  17. private bool _hasCheckedScript;
  18. private ScriptDocument? GetScriptDocument()
  19. {
  20. if (_hasCheckedScript)
  21. {
  22. return _script;
  23. }
  24. var settings = GetSettings();
  25. if (settings.ScriptEnabled && !string.IsNullOrWhiteSpace(settings.Script))
  26. {
  27. var document = new ScriptDocument(settings.Script);
  28. document.Properties.Add(new ScriptProperty("Results", null));
  29. if (!document.Compile())
  30. {
  31. throw new Exception("Script failed to compile!");
  32. }
  33. _script = document;
  34. }
  35. else
  36. {
  37. _script = null;
  38. }
  39. _hasCheckedScript = true;
  40. return _script;
  41. }
  42. public override bool BeforePost(IDataModel<TPostable> model)
  43. {
  44. if(GetScriptDocument() is ScriptDocument script)
  45. {
  46. return script.Execute(methodname: "BeforePost", parameters: new object[] { model });
  47. }
  48. else
  49. {
  50. return Poster.BeforePost(model);
  51. }
  52. }
  53. protected override IPostResult<TPostable> DoProcess(IDataModel<TPostable> model)
  54. {
  55. var settings = GetSettings();
  56. ICSVExport<TPostable> results;
  57. if (GetScriptDocument() is ScriptDocument script)
  58. {
  59. if (!script.Execute(methodname: "Process", parameters: new object[] { model }))
  60. {
  61. throw new Exception("Post Failed.");
  62. }
  63. var resultsObject = script.GetValue("Results");
  64. results = (resultsObject as ICSVExport<TPostable>)
  65. ?? throw new Exception($"Script 'Results' property expected to be ICSVExport<{typeof(TPostable)}>, got {resultsObject}");
  66. }
  67. else
  68. {
  69. results = Poster.Process(model);
  70. }
  71. var dlg = new SaveFileDialog()
  72. {
  73. FileName = settings.DefaultOutputFile,
  74. Filter = "CSV Files (*.csv)|*.csv"
  75. };
  76. if(dlg.ShowDialog() == true)
  77. {
  78. using var writer = new StreamWriter(dlg.FileName);
  79. using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
  80. csv.Context.RegisterClassMap(results.ClassMap.ClassMap);
  81. var method = typeof(CsvWriter).GetMethods()
  82. .Where(x => x.Name == nameof(CsvWriter.WriteRecords) && x.GetGenericArguments().Length == 1).First()
  83. .MakeGenericMethod(results.Type);
  84. method.Invoke(csv, new object?[] { results.Records });
  85. return results;
  86. }
  87. else
  88. {
  89. throw new PostCancelledException();
  90. }
  91. }
  92. public override void AfterPost(IDataModel<TPostable> model, IPostResult<TPostable> result)
  93. {
  94. if (GetScriptDocument() is ScriptDocument script)
  95. {
  96. // Ignoring 'result', because this is actually the 'Results' field of the script class.
  97. script.Execute(methodname: "AfterPost", parameters: new object[] { model });
  98. }
  99. else
  100. {
  101. Poster.AfterPost(model, result);
  102. }
  103. }
  104. }