Skip to content

Commit 07a8ea6

Browse files
CopilotJusterZhu
andauthored
Refactor Strategy classes to eliminate duplication using Template Method pattern (#109)
* Initial plan * Refactor Strategy classes to eliminate code duplication Co-authored-by: JusterZhu <11714536+JusterZhu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JusterZhu <11714536+JusterZhu@users.noreply.github.com>
1 parent 6c5fb26 commit 07a8ea6

5 files changed

Lines changed: 192 additions & 314 deletions

File tree

src/c#/GeneralUpdate.ClientCore/Strategys/LinuxStrategy.cs

Lines changed: 16 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
using System;
22
using System.Diagnostics;
33
using System.IO;
4-
using System.Threading.Tasks;
54
using GeneralUpdate.ClientCore.Pipeline;
6-
using GeneralUpdate.Common.FileBasic;
75
using GeneralUpdate.Common.Internal;
86
using GeneralUpdate.Common.Internal.Bootstrap;
97
using GeneralUpdate.Common.Internal.Event;
108
using GeneralUpdate.Common.Internal.Pipeline;
119
using GeneralUpdate.Common.Internal.Strategy;
1210
using GeneralUpdate.Common.Shared;
1311
using GeneralUpdate.Common.Shared.Object;
14-
using GeneralUpdate.Common.Shared.Object.Enum;
15-
using GeneralUpdate.Common.Shared.Service;
1612

1713
namespace GeneralUpdate.ClientCore.Strategys;
1814

@@ -21,76 +17,24 @@ namespace GeneralUpdate.ClientCore.Strategys;
2117
/// </summary>
2218
public class LinuxStrategy : AbstractStrategy
2319
{
24-
private GlobalConfigInfo _configinfo = new();
25-
26-
public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter;
27-
28-
public override async Task ExecuteAsync()
20+
protected override PipelineContext CreatePipelineContext(VersionInfo version, string patchPath)
2921
{
30-
try
31-
{
32-
var status = ReportType.None;
33-
var patchPath = StorageManager.GetTempDirectory(Patchs);
34-
foreach (var version in _configinfo.UpdateVersions)
35-
{
36-
try
37-
{
38-
var context = new PipelineContext();
39-
//Common
40-
context.Add("ZipFilePath",
41-
Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}"));
42-
//hash middleware
43-
context.Add("Hash", version.Hash);
44-
//zip middleware
45-
context.Add("Format", _configinfo.Format);
46-
context.Add("Name", version.Name);
47-
context.Add("Encoding", _configinfo.Encoding);
48-
//patch middleware
49-
context.Add("SourcePath", _configinfo.InstallPath);
50-
context.Add("PatchPath", patchPath);
51-
context.Add("PatchEnabled", _configinfo.PatchEnabled);
52-
//blacklist
53-
context.Add("BlackFiles", _configinfo.BlackFiles);
54-
context.Add("BlackFileFormats", _configinfo.BlackFormats);
55-
context.Add("SkipDirectorys", _configinfo.SkipDirectorys);
56-
57-
var pipelineBuilder = new PipelineBuilder(context)
58-
.UseMiddlewareIf<PatchMiddleware>(_configinfo.PatchEnabled)
59-
.UseMiddleware<CompressMiddleware>()
60-
.UseMiddleware<HashMiddleware>();
61-
await pipelineBuilder.Build();
62-
status = ReportType.Success;
63-
}
64-
catch (Exception e)
65-
{
66-
status = ReportType.Failure;
67-
GeneralTracer.Error("The ExecuteAsync method in the GeneralUpdate.ClientCore.LinuxStrategy class throws an exception.", e);
68-
EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message));
69-
}
70-
finally
71-
{
72-
await VersionService.Report(_configinfo.ReportUrl
73-
, version.RecordId
74-
, status
75-
, version.AppType
76-
, _configinfo.Scheme
77-
, _configinfo.Token);
78-
}
79-
}
80-
81-
if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl))
82-
{
83-
OpenBrowser(_configinfo.UpdateLogUrl);
84-
}
22+
var context = base.CreatePipelineContext(version, patchPath);
23+
24+
// Add ClientCore-specific context items (blacklists for Linux)
25+
context.Add("BlackFiles", _configinfo.BlackFiles);
26+
context.Add("BlackFileFormats", _configinfo.BlackFormats);
27+
context.Add("SkipDirectorys", _configinfo.SkipDirectorys);
28+
29+
return context;
30+
}
8531

86-
Clear(patchPath);
87-
Clear(_configinfo.TempPath);
88-
}
89-
catch (Exception e)
90-
{
91-
GeneralTracer.Error("The ExecuteAsync method in the GeneralUpdate.ClientCore.LinuxStrategy class throws an exception." , e);
92-
EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message));
93-
}
32+
protected override PipelineBuilder BuildPipeline(PipelineContext context)
33+
{
34+
return new PipelineBuilder(context)
35+
.UseMiddlewareIf<PatchMiddleware>(_configinfo.PatchEnabled)
36+
.UseMiddleware<CompressMiddleware>()
37+
.UseMiddleware<HashMiddleware>();
9438
}
9539

9640
public override void StartApp()

src/c#/GeneralUpdate.ClientCore/Strategys/WindowsStrategy.cs

Lines changed: 14 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
using System;
22
using System.Diagnostics;
33
using System.IO;
4-
using System.Threading.Tasks;
54
using GeneralUpdate.ClientCore.Pipeline;
6-
using GeneralUpdate.Common.FileBasic;
75
using GeneralUpdate.Common.Internal;
86
using GeneralUpdate.Common.Internal.Bootstrap;
97
using GeneralUpdate.Common.Internal.Event;
108
using GeneralUpdate.Common.Internal.Pipeline;
119
using GeneralUpdate.Common.Internal.Strategy;
1210
using GeneralUpdate.Common.Shared;
1311
using GeneralUpdate.Common.Shared.Object;
14-
using GeneralUpdate.Common.Shared.Object.Enum;
15-
using GeneralUpdate.Common.Shared.Service;
1612

1713
namespace GeneralUpdate.ClientCore.Strategys;
1814

@@ -21,72 +17,22 @@ namespace GeneralUpdate.ClientCore.Strategys;
2117
/// </summary>
2218
public class WindowsStrategy : AbstractStrategy
2319
{
24-
private GlobalConfigInfo _configinfo = new();
25-
26-
public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter;
27-
28-
public override async Task ExecuteAsync()
20+
protected override PipelineContext CreatePipelineContext(VersionInfo version, string patchPath)
2921
{
30-
try
31-
{
32-
var status = ReportType.None;
33-
var patchPath = StorageManager.GetTempDirectory(Patchs);
34-
foreach (var version in _configinfo.UpdateVersions)
35-
{
36-
try
37-
{
38-
var context = new PipelineContext();
39-
//Common
40-
context.Add("ZipFilePath",
41-
Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}"));
42-
//hash middleware
43-
context.Add("Hash", version.Hash);
44-
//zip middleware
45-
context.Add("Format", _configinfo.Format);
46-
context.Add("Name", version.Name);
47-
context.Add("Encoding", _configinfo.Encoding);
48-
//patch middleware
49-
context.Add("SourcePath", _configinfo.InstallPath);
50-
context.Add("PatchPath", patchPath);
51-
context.Add("PatchEnabled", _configinfo.PatchEnabled);
52-
53-
var pipelineBuilder = new PipelineBuilder(context)
54-
.UseMiddlewareIf<PatchMiddleware>(_configinfo.PatchEnabled)
55-
.UseMiddleware<CompressMiddleware>()
56-
.UseMiddleware<HashMiddleware>();
57-
await pipelineBuilder.Build();
58-
status = ReportType.Success;
59-
}
60-
catch (Exception e)
61-
{
62-
status = ReportType.Failure;
63-
GeneralTracer.Error("The ExecuteAsync method in the GeneralUpdate.ClientCore.WindowsStrategy class throws an exception.", e);
64-
EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message));
65-
}
66-
finally
67-
{
68-
await VersionService.Report(_configinfo.ReportUrl
69-
, version.RecordId
70-
, status
71-
, version.AppType
72-
, _configinfo.Scheme
73-
, _configinfo.Token);
74-
}
75-
}
76-
77-
if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl))
78-
{
79-
OpenBrowser(_configinfo.UpdateLogUrl);
80-
}
22+
var context = base.CreatePipelineContext(version, patchPath);
23+
24+
// Add ClientCore-specific context items (blacklists are not needed for Windows in Core)
25+
// Keeping this override to maintain extensibility
26+
27+
return context;
28+
}
8129

82-
Clear(patchPath);
83-
Clear(_configinfo.TempPath);
84-
}
85-
catch (Exception e)
86-
{
87-
GeneralTracer.Error("The ExecuteAsync method in the GeneralUpdate.ClientCore.WindowsStrategy class throws an exception." , e);
88-
EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message));
89-
}
30+
protected override PipelineBuilder BuildPipeline(PipelineContext context)
31+
{
32+
return new PipelineBuilder(context)
33+
.UseMiddlewareIf<PatchMiddleware>(_configinfo.PatchEnabled)
34+
.UseMiddleware<CompressMiddleware>()
35+
.UseMiddleware<HashMiddleware>();
9036
}
9137

9238
public override void StartApp()

src/c#/GeneralUpdate.Common/Internal/Strategy/AbstractStrategy.cs

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,131 @@
44
using System.Runtime.InteropServices;
55
using System.Threading.Tasks;
66
using GeneralUpdate.Common.FileBasic;
7+
using GeneralUpdate.Common.Internal.Event;
8+
using GeneralUpdate.Common.Internal.Pipeline;
9+
using GeneralUpdate.Common.Shared;
710
using GeneralUpdate.Common.Shared.Object;
11+
using GeneralUpdate.Common.Shared.Object.Enum;
12+
using GeneralUpdate.Common.Shared.Service;
813

914
namespace GeneralUpdate.Common.Internal.Strategy
1015
{
1116
public abstract class AbstractStrategy : IStrategy
1217
{
1318
protected const string Patchs = "patchs";
19+
protected GlobalConfigInfo _configinfo = new();
1420

1521
public virtual void Execute() => throw new NotImplementedException();
1622

1723
public virtual void StartApp() => throw new NotImplementedException();
1824

19-
public virtual Task ExecuteAsync() => throw new NotImplementedException();
25+
public virtual async Task ExecuteAsync()
26+
{
27+
try
28+
{
29+
var status = ReportType.None;
30+
var patchPath = StorageManager.GetTempDirectory(Patchs);
31+
foreach (var version in _configinfo.UpdateVersions)
32+
{
33+
try
34+
{
35+
var context = CreatePipelineContext(version, patchPath);
36+
var pipelineBuilder = BuildPipeline(context);
37+
await pipelineBuilder.Build();
38+
status = ReportType.Success;
39+
}
40+
catch (Exception e)
41+
{
42+
status = ReportType.Failure;
43+
HandleExecuteException(e);
44+
}
45+
finally
46+
{
47+
await VersionService.Report(_configinfo.ReportUrl
48+
, version.RecordId
49+
, status
50+
, version.AppType
51+
, _configinfo.Scheme
52+
, _configinfo.Token);
53+
}
54+
}
55+
56+
if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl))
57+
{
58+
OpenBrowser(_configinfo.UpdateLogUrl);
59+
}
60+
61+
Clear(patchPath);
62+
Clear(_configinfo.TempPath);
63+
OnExecuteComplete();
64+
}
65+
catch (Exception e)
66+
{
67+
HandleExecuteException(e);
68+
}
69+
}
70+
71+
public virtual void Create(GlobalConfigInfo parameter) => _configinfo = parameter;
72+
73+
/// <summary>
74+
/// Creates the pipeline context with common and platform-specific parameters.
75+
/// Override this method to add platform-specific context parameters.
76+
/// </summary>
77+
protected virtual PipelineContext CreatePipelineContext(VersionInfo version, string patchPath)
78+
{
79+
var context = new PipelineContext();
80+
// Common parameters
81+
context.Add("ZipFilePath", Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}"));
82+
// Hash middleware
83+
context.Add("Hash", version.Hash);
84+
// Zip middleware
85+
context.Add("Format", _configinfo.Format);
86+
context.Add("Name", version.Name);
87+
context.Add("Encoding", _configinfo.Encoding);
88+
// Patch middleware
89+
context.Add("SourcePath", _configinfo.InstallPath);
90+
context.Add("PatchPath", patchPath);
91+
context.Add("PatchEnabled", _configinfo.PatchEnabled);
92+
93+
return context;
94+
}
95+
96+
/// <summary>
97+
/// Builds the pipeline with middleware components.
98+
/// Override this method to customize the pipeline for specific platforms.
99+
/// </summary>
100+
protected abstract PipelineBuilder BuildPipeline(PipelineContext context);
101+
102+
/// <summary>
103+
/// Called after ExecuteAsync completes successfully.
104+
/// Override this method to add platform-specific post-execution logic.
105+
/// </summary>
106+
protected virtual void OnExecuteComplete()
107+
{
108+
// Default implementation does nothing
109+
}
20110

21-
public virtual void Create(GlobalConfigInfo parameter) => throw new NotImplementedException();
111+
/// <summary>
112+
/// Handles exceptions during execution.
113+
/// Override this method to customize error handling.
114+
/// </summary>
115+
protected virtual void HandleExecuteException(Exception e)
116+
{
117+
var className = GetType().Name;
118+
GeneralTracer.Error($"Exception in {className}.ExecuteAsync method.", e);
119+
EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message));
120+
}
121+
122+
/// <summary>
123+
/// Checks if a file exists at the specified path.
124+
/// </summary>
125+
protected static string CheckPath(string path, string name)
126+
{
127+
if (string.IsNullOrWhiteSpace(path) || string.IsNullOrWhiteSpace(name))
128+
return string.Empty;
129+
var tempPath = Path.Combine(path, name);
130+
return File.Exists(tempPath) ? tempPath : string.Empty;
131+
}
22132

23133
protected static void OpenBrowser(string url)
24134
{

0 commit comments

Comments
 (0)