昨天突然脑洞大开,觉得WinForm客户端也可以做成MVC!想到就做!于是把以前做的一个WinForm工程拉出来,选了角色权限模块先试个水。
第一步:调整项目结构,调整后结构如下图:
第二步:拆分逻辑
原来整个窗体类里面包含了很多业务逻辑,这部分不用说,直接拆分到Controller里面,还有工具栏点击事件的处理逻辑,也同样分离出来放到Controller里面。拆分之后,窗体类就变成了一个纯粹的View了。至于Model,就是拖进一个叫Model的文件夹里面就好了。
第三步:处理命名空间变化带来的一系列问题。大概花了两小时,部分重构完成,程序运行正常!
总结:重构后逻辑更加清晰,任务更容易分解,也更容易进行单元测试。这个思路个人认为值得推广。
部分代码:
Manager:
using System;
using System.Collections.Generic;
using System.Linq;
using DevExpress.XtraBars;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraTreeList;
using Insight.WS.Client.Base.Role.Controller;
using Insight.WS.Client.Base.Role.Model;
using Insight.WS.Client.Common;
namespace Insight.WS.Client.Base.Role.View
{
public partial class Manager : MdiBase
{
#region 变量声明
public static List<RoleInfo> Roles;
public static RoleInfo Role;
private bool First = true;
#endregion
#region 构造函数
public Manager()
{
InitializeComponent();
// 注册事件
gdvRole.FocusedRowObjectChanged += gdvRole_FocusedRowObjectChanged;
treMember.CustomDrawNodeImages += CustomDrawNodeImages;
treModule.CustomDrawNodeImages += DrawNodeImages;
treAction.CustomDrawNodeImages += DrawNodeImages;
treData.CustomDrawNodeImages += DrawNodeImages;
}
#endregion
#region 界面事件处理
/// <summary>
/// 窗体加载时初始化控件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void RoleManage_Load(object sender, EventArgs e)
{
InitToolBar();
Roles = new List<RoleInfo>();
Role = new RoleInfo();
// 初始化角色列表
grdRole.DataSource = Roles;
Format.GridFormat(gdvRole);
// 初始化角色成员
treMember.SelectImageList = imgMember;
treMember.DataSource = Role.Members;
Format.TreeFormat(treMember);
// 初始化角色成员用户
grdUser.DataSource = Role.Users;
Format.GridFormat(gdvUser);
// 初始化业务模块列表
treModule.SelectImageList = imgPermission;
treModule.DataSource = Role.Modules;
Format.TreeFormat(treModule);
// 初始化操作权限列表
treAction.DataSource = Role.Actions;
Format.TreeFormat(treAction);
treAction.SelectImageList = imgPermission;
// 初始化数据权限列表
treData.DataSource = Role.Datas;
Format.TreeFormat(treData);
treData.SelectImageList = imgData;
}
/// <summary>
/// 窗体显示时加载数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Manager_Shown(object sender, EventArgs e)
{
General.InitRoleList();
grdRole.DataSource = Roles;
gdvRole.MoveFirst();
}
/// <summary>
/// 角色列表选中行变化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void gdvRole_FocusedRowObjectChanged(object sender, FocusedRowObjectChangedEventArgs e)
{
Role = (RoleInfo) gdvRole.GetFocusedRow();
var dict = new Dictionary<string, bool>
{
{"DeleteRole", !Role.BuiltIn},
{"AddMember", !Role.BuiltIn}
};
SwitchItemStatus(dict);
treMember.DataSource = Role.Members;
treMember.ExpandAll();
grdUser.DataSource = Role.Users;
treData.DataSource = Role.Datas;
treData.ExpandToLevel(0);
treData.MoveFirst();
treAction.DataSource = Role.Actions;
treAction.ExpandToLevel(0);
treAction.MoveFirst();
treModule.DataSource = Role.Modules;
treModule.ExpandAll();
treModule.MoveFirst();
if (!First) return;
tabPermission.SelectedTabPageIndex = 1;
tabPermission.SelectedTabPageIndex = 0;
First = false;
}
/// <summary>
/// 切换角色成员
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treMember_FocusedNodeChanged(object sender, FocusedNodeChangedEventArgs e)
{
if (treMember.FocusedNode == null) return;
var canRemove = !Role.BuiltIn && (int)treMember.FocusedNode.GetValue("NodeType") != 0;
var dict = new Dictionary<string, bool>
{
{"Remove", canRemove}
};
SwitchItemStatus(dict);
}
/// <summary>
/// 双击角色列表编辑当前所选角色
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void gdvRole_DoubleClick(object sender, EventArgs e)
{
var id = (Guid) gdvRole.GetFocusedDataRow()["ID"];
var edit = barManager.Items["EditRole"];
if (gdvRole.FocusedRowHandle < 0 || !edit.Enabled) return;
Event.RoleEdit(true, id);
}
/// <summary>
/// 显示角色成员的类型图标
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CustomDrawNodeImages(object sender, CustomDrawNodeImagesEventArgs e)
{
if (e.Node.Level != 0) return;
e.SelectImageIndex = Convert.ToInt32(e.Node.GetValue("MemberId").ToString().Substring(0, 1));
}
/// <summary>
/// 重绘模块功能树节点图标
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DrawNodeImages(object sender, CustomDrawNodeImagesEventArgs e)
{
e.SelectImageIndex = (int)e.Node.GetValue("Type");
}
/// <summary>
/// 重载菜单列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected override void item_ItemClick(object sender, ItemClickEventArgs e)
{
switch (e.Item.Name)
{
case "Refresh":
General.InitRoleList();
break;
case "NewRole":
Event.RoleEdit(false, Guid.Empty);
gdvRole.FocusedRowHandle = gdvRole.GetRowHandle(Roles.Count - 1);
break;
case "EditRole":
var id = (Guid)gdvRole.GetFocusedDataRow()["ID"];
Event.RoleEdit(true, id);
break;
case "DeleteRole":
Event.RoleDelete();
gdvRole.RefreshData();
break;
case "AddMember":
Event.MemberAdd();
break;
case "Remove":
var mid = (Guid) treMember.FocusedNode.GetValue("ID");
var member = Role.Members.Single(m => m.ID == mid);
Event.MemberRemove(member);
treMember.RefreshDataSource();
break;
}
}
#endregion
}
}
using System;
using System.Windows.Forms;
using Insight.WS.Client.Base.Role.Model;
using Insight.WS.Client.Base.Role.View;
using static Insight.WS.Client.Common.Util.Message;
namespace Insight.WS.Client.Base.Role.Controller
{
public class Event
{
#region Manager
/// <summary>
/// 新建/编辑当前所选角色
/// </summary>
/// <param name="isEdit"></param>
/// <param name="id"></param>
public static void RoleEdit(bool isEdit, Guid id)
{
var dig = new Wizard
{
IsEdit = isEdit,
ObjectId = id
};
dig.Close();
}
/// <summary>
/// 删除当前所选角色
/// </summary>
public static void RoleDelete()
{
var msg = $"您确定要删除角色【{Manager.Role.Name}】吗?\r\n角色删除后将无法恢复!";
if (ShowConfirm(msg) != DialogResult.OK) return;
var result = Repository.RemoveRole(Manager.Role.ID);
if (!result.Successful)
{
ShowError($"{result.Message}\r\n对不起,角色【{Manager.Role.Name}】删除失败!如多次删除失败,请联系管理员。");
return;
}
Manager.Roles.Remove(Manager.Role);
}
/// <summary>
/// 为当前所选角色添加成员
/// </summary>
public static void MemberAdd()
{
var dig = new Member();
dig.Close();
}
/// <summary>
/// 删除当前所选角色成员
/// </summary>
public static void MemberRemove(RoleMember member)
{
var msg = $"您确定要移除角色成员【{member.Member}】吗?\r\n角色成员被移除后相应用户将失去该角色赋予的权限!";
if (ShowConfirm(msg) != DialogResult.OK) return;
var result = Repository.RemoveRoleMember(member.MemberId, member.NodeType);
if (!result.Successful)
{
ShowError($"{result.Message}\r\n对不起,角色成员【{member.Member}】移除失败!如多次移除失败,请联系管理员。");
return;
}
Manager.Role.Members.Remove(member);
}
#endregion
}
}
Repository:
using System;
using Insight.WS.Client.Common.Entity;
using static Insight.WS.Client.Common.Util.HttpHelper;
using static Insight.WS.Client.Common.Util.Utils;
namespace Insight.WS.Client.Base.Role.Controller
{
public class Repository
{
/// <summary>
/// 删除指定角色
/// </summary>
/// <returns>JsonResult</returns>
public static JsonResult RemoveRole(Guid id)
{
var url = BaseServer + $"r/roles/{id}";
return HttpRequest(url, "DELETE", AutherKey);
}
/// <summary>
/// 获取所有角色
/// </summary>
/// <returns>JsonResult</returns>
public static JsonResult GetRoles()
{
var url = BaseServer + "r/roles";
return HttpRequest(url, "GET", AutherKey);
}
/// <summary>
/// 删除指定角色成员
/// </summary>
/// <param name="id">成员关系ID</param>
/// <param name="type">成员类型</param>
/// <returns>JsonResult</returns>
public static JsonResult RemoveRoleMember(Guid id, int type)
{
var url = BaseServer + $"r/roles/members/{id}?type={type}";
return HttpRequest(url, "DELETE", AutherKey);
}
}
}