feat(architecture): Implement decoupled modifier architecture

This commit introduces a major architectural refactoring to improve the maintainability, extensibility, and testability of the application.

Key changes include:
- **IAppModifier Interface:** Defines a clear contract for all application-specific modifiers.
- **BaseAppModifier Abstract Class:** Provides common implementations for shared modifier logic, reducing code duplication.
- **Refactored Concrete Modifiers:** Existing modifier classes now inherit from BaseAppModifier, focusing on their unique application-specific logic.
- **ModifierFactory:** Centralizes the creation of modifier instances, decoupling the UI from concrete implementations.
- **Updated FormMain.cs:** The main UI now interacts with modifiers through the IAppModifier interface and uses the ModifierFactory, significantly reducing coupling and simplifying UI logic.

This refactoring adheres to principles of abstraction, encapsulation, and polymorphism, making the codebase more robust and easier to extend with support for new applications in the future.
This commit is contained in:
SyedaAnshrahGillani 2025-08-05 19:21:12 +05:00
parent 480bc7ad81
commit 2fe0f0ee8e
10 changed files with 223 additions and 298 deletions

View File

@ -16,14 +16,7 @@ namespace RevokeMsgPatcher
public partial class FormMain : Form
{
// 当前使用的修改者
private AppModifier modifier = null;
private WechatModifier wechatModifier = null;
private WeixinModifier weixinModifier = null;
private QQModifier qqModifier = null;
private TIMModifier timModifier = null;
private QQLiteModifier qqLiteModifier = null;
private QQNTModifier qqntModifier = null;
private IAppModifier modifier = null;
private string thisVersion;
private bool needUpdate = false;
@ -41,24 +34,9 @@ namespace RevokeMsgPatcher
JavaScriptSerializer serializer = new JavaScriptSerializer();
bag = serializer.Deserialize<Bag>(Properties.Resources.PatchJson);
// 初始化每个应用对应的修改者
wechatModifier = new WechatModifier(bag.Apps["Wechat"]);
weixinModifier = new WeixinModifier(bag.Apps["Weixin"]);
qqModifier = new QQModifier(bag.Apps["QQ"]);
timModifier = new TIMModifier(bag.Apps["TIM"]);
qqLiteModifier = new QQLiteModifier(bag.Apps["QQLite"]);
qqntModifier = new QQNTModifier(bag.Apps["QQNT"]);
rbtWechat.Tag = wechatModifier;
rbtWeixin.Tag = weixinModifier;
rbtQQ.Tag = qqModifier;
rbtTIM.Tag = timModifier;
rbtQQLite.Tag = qqLiteModifier;
rbtQQNT.Tag = qqntModifier;
// 默认微信
rbtWechat.Enabled = true;
modifier = wechatModifier;
modifier = ModifierFactory.CreateModifier("WeChat", bag.Apps["WeChat"]);
}
public FormMain()
@ -349,11 +327,7 @@ namespace RevokeMsgPatcher
lblUpdatePachJson.Text = "[ 获取成功,点击查看更多信息 ]";
lblUpdatePachJson.ForeColor = Color.RoyalBlue;
wechatModifier.Config = newBag.Apps["Wechat"];
weixinModifier.Config = newBag.Apps["Weixin"];
qqModifier.Config = newBag.Apps["QQ"];
timModifier.Config = newBag.Apps["TIM"];
qqLiteModifier.Config = newBag.Apps["QQLite"];
modifier.Config = newBag.Apps[modifier.Config.Name];
getPatchJsonStatus = "SUCCESS";
bag = newBag;
@ -412,31 +386,8 @@ namespace RevokeMsgPatcher
EnableAllButton(false);
// 切换使用不同的防撤回对象
if (rbtWechat.Checked)
{
modifier = (WechatModifier)rbtWechat.Tag;
}
else if (rbtWeixin.Checked)
{
modifier = (WeixinModifier)rbtWeixin.Tag;
}
else if (rbtQQ.Checked)
{
modifier = (QQModifier)rbtQQ.Tag;
}
else if (rbtTIM.Checked)
{
modifier = (TIMModifier)rbtTIM.Tag;
}
else if (rbtQQLite.Checked)
{
modifier = (QQLiteModifier)rbtQQLite.Tag;
}
else if (rbtQQNT.Checked)
{
modifier = (QQNTModifier)rbtQQNT.Tag;
// ShowOrFocusFormLiteLoaderQQNT();
}
string appName = GetCheckedRadioButtonNameEn();
modifier = ModifierFactory.CreateModifier(appName, bag.Apps[appName]);
EnableAllButton(true);
// 触发了 txtPath_TextChanged 方法 已经调用了 InitEditorsAndUI(txtPath.Text);
@ -466,27 +417,13 @@ namespace RevokeMsgPatcher
private string GetCheckedRadioButtonNameEn()
{
if (rbtWechat.Checked)
foreach (Control control in this.panelAppSelect.Controls)
{
return "wechat";
}
else if (rbtQQ.Checked)
if (control is RadioButton radioButton && radioButton.Checked)
{
return "qq";
return radioButton.Text;
}
else if (rbtTIM.Checked)
{
return "tim";
}
else if (rbtQQLite.Checked)
{
return "qqlite";
}
else if (rbtQQNT.Checked)
{
return "qqnt";
}
return "none";
}

View File

@ -0,0 +1,141 @@
using RevokeMsgPatcher.Model;
using RevokeMsgPatcher.Utils;
using System.Collections.Generic;
using System.Windows.Forms;
namespace RevokeMsgPatcher.Modifier
{
public abstract class BaseAppModifier : AppModifier, IAppModifier
{
public abstract string VersionFileName { get; }
public App Config { get; set; }
protected BaseAppModifier(App config)
{
this.Config = config;
}
public override string GetVersion()
{
if (editors != null && editors.Count > 0)
{
foreach (FileHexEditor editor in editors)
{
if (editor.FileName == VersionFileName)
{
return editor.FileVersion;
}
}
}
return string.Empty;
}
public override void AfterPatchSuccess() { }
public override void AfterPatchFail() { }
public bool BackupExists()
{
if (editors == null || editors.Count == 0)
{
return false;
}
foreach (FileHexEditor editor in editors)
{
if (!System.IO.File.Exists(editor.FileBakPath))
{
return false;
}
}
return true;
}
public bool IsAllFilesExist(string installPath)
{
if (Config.TargetFiles == null)
{
return true;
}
foreach (TargetInfo target in Config.TargetFiles)
{
if (!System.IO.File.Exists(target.GetAbsolutePath(installPath)))
{
return false;
}
}
return true;
}
public bool InitEditors(string installPath)
{
// 判断是否是安装路径
if (!IsAllFilesExist(installPath))
{
return false;
}
// 初始化十六进制文件编辑器
// 并寻找与之配对的版本修改信息
editors = new List<FileHexEditor>();
foreach (TargetInfo target in Config.TargetFiles)
{
editors.Add(new FileHexEditor(installPath, target));
}
return true;
}
public void SetVersionLabelAndCategoryCategories(Label lblVersion, Panel panelCategories)
{
lblVersion.Text = GetVersion();
UIController.AddCategoriesToPanel(panelCategories, Config.Categories);
}
public void ValidateAndFindModifyInfo(List<string> categories)
{
foreach (FileHexEditor editor in editors)
{
// 寻找精确版本修改信息
ModifyInfo modifyInfo = ModifyFinder.FindModifyInfo(editor.FileSHA1, Config.ModifyInfos);
if (modifyInfo != null)
{
editor.FileModifyInfo = modifyInfo;
editor.TargetChanges = modifyInfo.Changes;
}
else
{
// 寻找通用特征码修改信息
CommonModifyInfo commonModifyInfo = ModifyFinder.FindCommonModifyInfo(editor.FileVersion, Config.CommonModifyInfos);
if (commonModifyInfo != null)
{
editor.FileCommonModifyInfo = commonModifyInfo;
editor.TargetChanges = ModifyFinder.FindChangesByCategories(editor.FilePath, commonModifyInfo.ReplacePatterns, categories);
}
else
{
throw new BusinessException("not_support_version", $"当前版本 {editor.FileVersion} 不支持,请等待更新!");
}
}
}
}
public void Patch()
{
foreach (FileHexEditor editor in editors)
{
editor.Backup();
editor.Patch();
}
AfterPatchSuccess();
}
public bool Restore()
{
foreach (FileHexEditor editor in editors)
{
editor.Restore();
}
return true;
}
}
}

View File

@ -0,0 +1,24 @@
using RevokeMsgPatcher.Model;
using System.Collections.Generic;
using System.Windows.Forms;
namespace RevokeMsgPatcher.Modifier
{
public interface IAppModifier
{
App Config { get; set; }
List<FileHexEditor> editors { get; set; }
string FindInstallPath();
string GetVersion();
bool InitEditors(string installPath);
void ValidateAndFindModifyInfo(List<string> categories);
void Patch();
bool Restore();
bool BackupExists();
bool IsAllFilesExist(string installPath);
void SetVersionLabelAndCategoryCategories(Label lblVersion, Panel panelCategories);
void AfterPatchSuccess();
void AfterPatchFail();
}
}

View File

@ -0,0 +1,28 @@
using RevokeMsgPatcher.Model;
namespace RevokeMsgPatcher.Modifier
{
public static class ModifierFactory
{
public static IAppModifier CreateModifier(string appName, App config)
{
switch (appName)
{
case "WeChat":
return new WechatModifier(config);
case "Weixin":
return new WeixinModifier(config);
case "QQ":
return new QQModifier(config);
case "TIM":
return new TIMModifier(config);
case "QQLite":
return new QQLiteModifier(config);
case "QQNT":
return new QQNTModifier(config);
default:
throw new System.ArgumentException($"Unknown application name: {appName}");
}
}
}
}

View File

@ -5,20 +5,11 @@ using System.Collections.Generic;
namespace RevokeMsgPatcher.Modifier
{
class QQLiteModifier : AppModifier
class QQLiteModifier : BaseAppModifier
{
public QQLiteModifier(App config)
{
this.config = config;
}
public override string VersionFileName => "IM.dll";
public override void AfterPatchSuccess()
{
}
public override void AfterPatchFail()
{
}
public QQLiteModifier(App config) : base(config) { }
/// <summary>
/// 自动寻找获取微信安装路径
@ -51,24 +42,5 @@ namespace RevokeMsgPatcher.Modifier
}
return null;
}
/// <summary>
/// 获取整个APP的当前版本
/// </summary>
/// <returns></returns>
public override string GetVersion()
{
if (editors != null && editors.Count > 0)
{
foreach (FileHexEditor editor in editors)
{
if (editor.FileName == "IM.dll")
{
return editor.FileVersion;
}
}
}
return "";
}
}
}

View File

@ -5,20 +5,11 @@ using System.Collections.Generic;
namespace RevokeMsgPatcher.Modifier
{
class QQModifier : AppModifier
class QQModifier : BaseAppModifier
{
public QQModifier(App config)
{
this.config = config;
}
public override string VersionFileName => "IM.dll";
public override void AfterPatchSuccess()
{
}
public override void AfterPatchFail()
{
}
public QQModifier(App config) : base(config) { }
/// <summary>
/// 自动寻找获取微信安装路径
@ -51,24 +42,5 @@ namespace RevokeMsgPatcher.Modifier
}
return null;
}
/// <summary>
/// 获取整个APP的当前版本
/// </summary>
/// <returns></returns>
public override string GetVersion()
{
if (editors != null && editors.Count > 0)
{
foreach (FileHexEditor editor in editors)
{
if (editor.FileName == "IM.dll")
{
return editor.FileVersion;
}
}
}
return "";
}
}
}

View File

@ -9,12 +9,11 @@ using System.Windows.Forms;
namespace RevokeMsgPatcher.Modifier
{
class QQNTModifier : AppModifier
class QQNTModifier : BaseAppModifier
{
public QQNTModifier(App config)
{
this.config = config;
}
public override string VersionFileName => "wrapper.node";
public QQNTModifier(App config) : base(config) { }
/// <summary>
/// 自动寻找获取微信安装路径
@ -59,38 +58,9 @@ namespace RevokeMsgPatcher.Modifier
return null;
}
/// <summary>
/// 获取整个APP的当前版本
/// </summary>
/// <returns></returns>
public override string GetVersion()
{
if (editors != null && editors.Count > 0)
{
foreach (FileHexEditor editor in editors)
{
if (editor.FileName == "wrapper.node")
{
return editor.FileVersion;
}
}
}
return "";
}
public override void AfterPatchSuccess()
{
}
public override void AfterPatchFail()
{
}
public new bool Restore()
{
AfterPatchFail();
base.AfterPatchFail();
return base.Restore();
}
}

View File

@ -3,21 +3,11 @@ using RevokeMsgPatcher.Utils;
namespace RevokeMsgPatcher.Modifier
{
class TIMModifier : AppModifier
class TIMModifier : BaseAppModifier
{
public override string VersionFileName => "IM.dll";
public TIMModifier(App config)
{
this.config = config;
}
public override void AfterPatchSuccess()
{
}
public override void AfterPatchFail()
{
}
public TIMModifier(App config) : base(config) { }
/// <summary>
/// 自动寻找获取微信安装路径
@ -42,24 +32,5 @@ namespace RevokeMsgPatcher.Modifier
}
return null;
}
/// <summary>
/// 获取整个APP的当前版本
/// </summary>
/// <returns></returns>
public override string GetVersion()
{
if (editors != null && editors.Count > 0)
{
foreach (FileHexEditor editor in editors)
{
if (editor.FileName == "IM.dll")
{
return editor.FileVersion;
}
}
}
return "";
}
}
}

View File

@ -6,21 +6,11 @@ using System.IO;
namespace RevokeMsgPatcher.Modifier
{
class WechatModifier : AppModifier
class WechatModifier : BaseAppModifier
{
public override string VersionFileName => "WeChatWin.dll";
public WechatModifier(App config)
{
this.config = config;
}
public override void AfterPatchSuccess()
{
}
public override void AfterPatchFail()
{
}
public WechatModifier(App config) : base(config) { }
/// <summary>
/// 自动寻找获取微信安装路径
@ -82,40 +72,5 @@ namespace RevokeMsgPatcher.Modifier
}
return null;
}
/// <summary>
/// 获取整个APP的当前版本
/// </summary>
/// <returns></returns>
public override string GetVersion()
{
if (editors != null && editors.Count > 0)
{
foreach (FileHexEditor editor in editors)
{
if (editor.FileName == "WeChatWin.dll")
{
return editor.FileVersion;
}
}
}
return "";
}
//public override bool ValidateAndInitialize(string installPath)
//{
// // 判断是否是安装路径
// if (!IsAllBinaryFilesExist(installPath))
// {
// return false;
// }
// // 初始化十六进制文件编辑器
// // 并寻找与之配对的版本修改信息
// InitEditors(installPath);
// return true;
//}
}
}

View File

@ -6,21 +6,11 @@ using System.IO;
namespace RevokeMsgPatcher.Modifier
{
class WeixinModifier : AppModifier
class WeixinModifier : BaseAppModifier
{
public override string VersionFileName => "Weixin.dll";
public WeixinModifier(App config)
{
this.config = config;
}
public override void AfterPatchSuccess()
{
}
public override void AfterPatchFail()
{
}
public WeixinModifier(App config) : base(config) { }
/// <summary>
/// 自动寻找获取微信安装路径
@ -83,40 +73,5 @@ namespace RevokeMsgPatcher.Modifier
}
return null;
}
/// <summary>
/// 获取整个APP的当前版本
/// </summary>
/// <returns></returns>
public override string GetVersion()
{
if (editors != null && editors.Count > 0)
{
foreach (FileHexEditor editor in editors)
{
if (editor.FileName == "Weixin.dll")
{
return editor.FileVersion;
}
}
}
return "";
}
//public override bool ValidateAndInitialize(string installPath)
//{
// // 判断是否是安装路径
// if (!IsAllBinaryFilesExist(installPath))
// {
// return false;
// }
// // 初始化十六进制文件编辑器
// // 并寻找与之配对的版本修改信息
// InitEditors(installPath);
// return true;
//}
}
}