曾经的我觉得,同样的表单,若有后台代码,那么它相应的应该是一套业务,仅仅能为这个功能服务。可是后来的需求打翻了我的认识。
曾经我做的一条线是实现例如以下功能
这个是一条线的功能,结合工作流,4个活动点相应四个表单。
后来在做第四个功能线的时候发现一部分与功能一同样。
可是当中用到的类与对象却不同样。
可是页面是略微变化。
还是能够复用页面的。
需求功能大题是一样的。类的设计是不同的子类设计。那么就须要改动原来的代码实现了。
看设计图
先前全部后台的泛型为第一个,兴许的复用页面须要用第二个泛型类,可是他们都共同继承同一个基类。怎样依据不同的功能保存不同的泛型类。
使一个表单兼容两个不同的类型,这是设计时须要考虑的。
我们的解决方案是在基类中加入了一个selfType的属性。标记了一个使用者的类型。这样在准备数据的时候传递的是基类。可是自身却携带了是某一个类型。
而到了详细的表单页面时,依据自身的selfType推断类型,继而转换不同的子类,保存数据。
我们来看看一个实例吧
设计的思路:
- 首先载入基类,而后推断是否为空,若为空创建第子类的类型
- 若不为空,依据父类携带类型,推断是子类的哪个类型,依据Id,载入子类,将父类指向子类
- 表单依据父类携带的类型,保存时进行数据类型强转
Control准备数据
//下面为MVC中control中数据准备
String resourceID = process.ResourceID;//父类载入数据,兴许推断是否为空,指向不同自来
EnsureKeyedCapabilityIndicatorFormBase data = EnsureKeyedCapabilityIndicatorFormBaseAdapter.Instance.Load(resourceID);
int operateYear = WebUtility.GetRequestQueryValue("operateYear", DateTime.Now.SimulateTime().Year);
if (data == null)
{
//父类为空,应用指向子类。创建子类对象。//方便兴许转换类型
data = new EnsureGroupKeyedCapabilityIndicatorForm()
{
SelfTypeName = typeof(EnsureGroupKeyedCapabilityIndicatorForm).Name,
ID = resourceID,
CreatorID = user.ID,
CreatorName = user.DisplayName,
CreateTime = DateTime.Now.SimulateTime(),
OperateYear = operateYear,
PlanStartYear = operateYear + 1,
Subject = operateYear + "确认历史能力",
ProcState = WfProcessStatus.NotRunning
};
var companyCapabilitySummary = data.InitDefaultCompanyCapability();
CompanyCapabilitySummaryTransAdapter.Instance.Update(companyCapabilitySummary);
EnsureGroupKeyedCapabilityIndicatorFormAdapter.Instance.Update((EnsureGroupKeyedCapabilityIndicatorForm)data);
}
else
{
//已经是有数据了,依据父类携带类型,推断是子类的哪个类型。进行类型载入
if (data.SelfTypeName == typeof(EnsureGroupKeyedCapabilityIndicatorForm).Name)
{
data = EnsureGroupKeyedCapabilityIndicatorFormAdapter.Instance.Load(resourceID);
}
else
{
data = EnsureBusinessModelKeyedCapabilityIndicatorFormAdapter.Instance.Load(resourceID);
var comanys = CompanyCapabilitySummaryTransAdapter.Instance.LoadByFormCode(resourceID);
var enBusines = (EnsureBusinessModelKeyedCapabilityIndicatorForm)data;
//子类还须要进行辨别是新增还是已经存在的商业模式,
if (enBusines.BusinessModelExsitsType == BusinessModelExsitsTypeEnum.Exsits)
{
//已经在初始化自身
if (comanys.Count == 0)
{
var companyCapabilitySummary = data.InitDefaultCompanyCapability();
CompanyCapabilitySummaryTransAdapter.Instance.Update(companyCapabilitySummary);
}
}
else
{
//新增,使用公共取代自身
if (comanys.Count == 0)
{
var companyCapabilitySummary = data.InitDefaultCompanyCapability(CompanyCapabilitySummaryTrans.IndustryAvgCodeConst);
CompanyCapabilitySummaryTransAdapter.Instance.Update(companyCapabilitySummary);
}
}
}
}
//返回基类数据,可是指向的却是之类。
return new FormCommandStateGenericBase<EnsureKeyedCapabilityIndicatorFormBase>() { Data = data };
表单后台保存
表单的继承类型为基类
public partial class EnsureCapabilityIndicatorHistoryView : ExtendViewBase<FormCommandStateGenericBase<EnsureKeyedCapabilityIndicatorFormBase>, EnsureKeyedCapabilityIndicatorFormBase>
{
//ViewData中DatA 为control中传递过来的数据(data)
protected override void SaveApplicationData(WfExecutorDataContext datacontext)
{
//还是依据携带类型辨别是哪个继承类,
if (this.ViewData.Data.SelfTypeName == typeof(EnsureGroupKeyedCapabilityIndicatorForm).Name)
{
//保存时进行数据类型强转(若没有control中的父类指向子类引用,这里的转换是报错的)
EnsureGroupKeyedCapabilityIndicatorFormAdapter.Instance.Update((EnsureGroupKeyedCapabilityIndicatorForm)this.ViewData.Data);
}
else
{
EnsureBusinessModelKeyedCapabilityIndicatorFormAdapter.Instance.Update((EnsureBusinessModelKeyedCapabilityIndicatorForm)this.ViewData.Data);
}
}
}
小结:
这里用到的实质为面向对象中的继承特性。父类引用指向子类。这个相信大家非常熟悉的。如Ilist<string> names= new List<string>()。实例化的是一个IList的父类。仅仅能使用父类的属性。若想使用List的属性,如List的forEach属性,这种实例化是不能够使用的,必须将names强转为List。
就是一个非常好的样例。可是若能透彻的明确,并在设计中熟练使用。还真的是须要透彻的了解,多多思考。