YbSoftwareFactory 代码生成插件【五】:具有超炫界面效果的WPF完整解决方案的代码生成插件
YbSoftwareFactory 的最新插件,面向WPF的解决方案,具有令人震撼、超级绚丽的界面效果。把该插件的dll文件及相关的模板文件、压缩文件放到Plugin文件夹下即可在 YbSoftwareFactory 的主应用程序中识别并运行。
本插件在YbSoftwareFactory中的界面效果如下,可单独生成实体层代码、MVVM层代码、WPF层代码及完整的可直接在VS中调试运行的解决方案:
本插件主要包含如下代码文件:
其中CastleDxWpfPluginRepositoryBase为本插件的核心类,主要代码如下:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Yb.CustomTemplating;
using Yb.DbSchemaReader.DataSchema;
using Yb.Plugin.Base;
using Yb.Utility;
namespace Yb.Plugin.CastleDevExpress.Wpf
{
public abstract class CastleDxWpfPluginRepositoryBase : PluginRepositoryBase
{
private int _totalCount = 0;
private int _currentIndex = 0;
protected virtual int GetShouldBuildCodeNum(int listCount)
{
var templateCount = GetTemplateInfos().Count();
return listCount * (templateCount);
}
/// <summary>
/// 生成代码
/// </summary>
/// <param name="dataSource"></param>
/// <param name="templateInfos"></param>
/// <returns></returns>
public override IEnumerable<TemplateInfo> BuildCodes(object dataSource, IEnumerable<TemplateInfo> templateInfos, object dataSourceInfo)
{
//参数类型转换
var tableInfos = BaseInfoUtility.ObjectToDatabaseTableList(dataSource).Where(c => c.Checked).ToList();
//生成结果
var templateList = new List<TemplateInfo>();
_totalCount = GetShouldBuildCodeNum(tableInfos.Count);
_currentIndex = 0;
foreach (var templateInfo in templateInfos)
{
if (!templateInfo.BuildEnable) continue;
//读模板信息
templateInfo.TemplateContent = FileUtility.ReadFile(templateInfo.TemplateRelativePath);
//判断模板类型,是否每张表都需生成一个模板
if ((templateInfo.Tag & StaticResources.IsTableInfoListOfTemplateArg) == 0)
{
foreach (var tableInfo in tableInfos)
{
//复制模板,防止生成后下一个循环被覆盖
var currentTemplateInfo = (TemplateInfo)templateInfo.Clone();
//生成代码
BuildTableCode("CurrentTable", templateList, tableInfo, currentTemplateInfo);
}
}
else
{
//生成 App.Config 文件
if (templateInfo.ExportFileNameFormatString.Equals("App.config", StringComparison.OrdinalIgnoreCase))
{
var sourceInfo = dataSourceInfo as DataSourceInfo;
//创建Web.Config代码
if (sourceInfo != null)
BuildAppConfigCode(templateList, templateInfo, tableInfos, sourceInfo);
}else
{
//创建如项目文件等需要传入“表对象集合”为参数的模板代码
BuildTablesCode(templateList, templateInfo, tableInfos);
}
}
}
return templateList;
}
/// <summary>
/// 创建和表有关的代码
/// </summary>
/// <param name="templateArgName"></param>
/// <param name="templateList"></param>
/// <param name="tableInfo"></param>
/// <param name="templateInfo"></param>
private void BuildTableCode(string templateArgName, List<TemplateInfo> templateList, DatabaseTable tableInfo, TemplateInfo templateInfo)
{
try
{
//代码生成关键代码,根据模板生成代码
templateInfo.ExportContent = Template.Transform(templateInfo.TemplateContent, templateArgName,
tableInfo);
//更新模板标题,标题也是要生成文件的名称
templateInfo.Title = BaseInfoUtility.ReplaceString(templateInfo.ExportFileNameFormatString,
tableInfo.Name);
templateInfo.ExportRelativePath = BaseInfoUtility.ReplaceString(templateInfo.ExportRelativePathFormatString,
tableInfo.Name);
AddCodeList(templateList, templateInfo);
}
catch (Exception er)
{
NotifyException(templateInfo, er);
}
}
/// <summary>
/// 创建和数据库有关的代码
/// </summary>
/// <param name="templateList"></param>
/// <param name="templateInfo"></param>
/// <param name="tableInfos"></param>
private void BuildTablesCode(List<TemplateInfo> templateList, TemplateInfo templateInfo, List<DatabaseTable> tableInfos)
{
try
{
templateInfo.ExportContent = Template.Transform(templateInfo.TemplateContent, "TableInfos",
tableInfos);
templateInfo.Title = templateInfo.ExportFileNameFormatString;
templateInfo.ExportRelativePath = templateInfo.ExportRelativePathFormatString;
AddCodeList(templateList, templateInfo);
}
catch (Exception er)
{
NotifyException(templateInfo, er);
}
}
/// <summary>
/// 创建Web.Config 代码
/// </summary>
/// <param name="templateList"></param>
/// <param name="templateInfo"></param>
/// <param name="tableInfos"></param>
private void BuildAppConfigCode(List<TemplateInfo> templateList, TemplateInfo templateInfo, List<DatabaseTable> tableInfos, DataSourceInfo dataSourceInfo)
{
try
{
templateInfo.ExportContent = Template.Transform(templateInfo.TemplateContent, "DataSourceInfo",
dataSourceInfo);
templateInfo.Title = templateInfo.ExportFileNameFormatString;
templateInfo.ExportRelativePath = templateInfo.ExportRelativePathFormatString;
AddCodeList(templateList, templateInfo);
}
catch (Exception er)
{
NotifyException(templateInfo, er);
}
}
/// <summary>
/// 代码创建后进行事件通知
/// </summary>
/// <param name="templateList"></param>
/// <param name="templateInfo"></param>
private void AddCodeList(List<TemplateInfo> templateList, TemplateInfo templateInfo)
{
templateList.Add(templateInfo);
_currentIndex++;
OnNotifyChanged(new NotifyChangedEventArgs(NotifyType.Seccessful,
string.Format("代码 {0} 生成成功", templateInfo.Title)
, _currentIndex, _totalCount));
}
/// <summary>
/// 通知代码创建失败
/// </summary>
/// <param name="templateInfo"></param>
/// <param name="er"></param>
private void NotifyException(TemplateInfo templateInfo, Exception er)
{
_currentIndex++;
OnNotifyChanged(new NotifyChangedEventArgs(NotifyType.Error,
string.Format("代码 {0} 生成失败。{1}", templateInfo.Title, er.Message),
_currentIndex, _totalCount));
}
public override IEnumerable<TemplateInfo> GetTemplateInfos()
{
return StaticResources.GetTemplateInfos();
}
}
}
所生成的代码的主要特征如下:
1、主界面是一个基本Google在线地图的GIS应用,对GIS感兴趣的朋友可以进一步深入了解。
添加GIS图层的代码如下:
/// 添加GIS图层
/// </summary>
private void AddPictureMarkerAndTextGraphics()
{
GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;
var graphics=graphicsLayer.Graphics;
if(graphics==null || graphics.Count==0) return;
var graphic = graphics[0];
if (!graphic.Attributes.ContainsKey("Description"))
graphic.Attributes.Add("Description",
"专注于代码生成器、组件、控件、中间件的开发");
if (!graphic.Attributes.ContainsKey("QQ"))
graphic.Attributes.Add("QQ", "1335255648 19892257");
}
GIS界面效果图如下(可是有动画效果的,试过才知道哈):
2、合理的布局、超炫的界面主题、方便易用的界面,简直就是OutLook样式和Rabbion样式的完美结合,点击OutLook导航中的列表项可自动加载其对应的Rabbion控件菜单。
3、可切换界面主题,可分别设置并为每个登录用户下每个功能模块单独自动保存相应的界面设置和布局(如个性化的分组、显示或隐藏分割线、显示或隐藏行瞄点等等),超级强悍:
4、真正模块化的设计,一键生成源代码并可直接在VS中运行。插件所生成的完整源代码使你可随心所欲地对代码进行根据个性化的修改。
5、多层架构,MVVM层使用Catel,界面层使用DevExpress。
解决方案的项目组织结构图:
基于Catel的Command模式Demo代码如下:
public ModuleObjectDetail(EditableObject editObject, object tag)
: this(editObject) {
Tag = tag;
}
public ModuleObjectDetail(EditableObject editObject) {
EditObject = editObject;
CommandSave = new Command<object>(OnCommandSaveExecute, OnCommandSaveCanExecute);
CommandSaveAndDispose = new Command<object>(OnCommandSaveAndDisposeExecute, OnCommandSaveAndDisposeCanExecute);
CommandClose = new Command<object>(OnCommandCloseExecute, OnCommandCloseCanExecute);
}
6、自动集成完整的用户管理、角色管理、权限可控制到每个细粒度的操作,如果数据库类型为SQL Server,则还将为您自动安装和权限管理有关的表结构。让你更加专注于业务逻辑层的开发:
7、已集成基本的字段验证功能。
界面集成的代码超级简单,只需在对应的XAML文件中对要验证的实体属性指定如下语句即可,字段级的验证可是通用的哦(基本的验证代码在代码生成的时候已为您自动集成),Demo代码如下:
<helpers:ValidationInfo EditName0="IDEdit" Rule="{StaticResource ValidationRuleForField}" />
<helpers:BindingInfo ElementName="CodeEdit" Property="{x:Static dxe:BaseEdit.EditValueProperty}" Value="{Binding EditObject.YbObject.Code, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<helpers:ValidationInfo EditName1="CodeEdit" Rule="{StaticResource ValidationRuleForField}" />
<helpers:BindingInfo ElementName="NameEdit" Property="{x:Static dxe:BaseEdit.EditValueProperty}" Value="{Binding EditObject.YbObject.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<helpers:ValidationInfo EditName2="NameEdit" Rule="{StaticResource ValidationRuleForField}" />
<helpers:BindingInfo ElementName="BeginTimeEdit" Property="{x:Static dxe:BaseEdit.EditValueProperty}" Value="{Binding EditObject.YbObject.BeginTime, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<helpers:ValidationInfo EditName3="BeginTimeEdit" Rule="{StaticResource ValidationRuleForField}" />
<helpers:BindingInfo ElementName="TimeLimitEdit" Property="{x:Static dxe:BaseEdit.EditValueProperty}" Value="{Binding EditObject.YbObject.TimeLimit, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<helpers:ValidationInfo EditName4="TimeLimitEdit" Rule="{StaticResource ValidationRuleForField}" />
<helpers:BindingInfo ElementName="CategoryEdit" Property="{x:Static dxe:BaseEdit.EditValueProperty}" Value="{Binding EditObject.YbObject.Category, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<helpers:ValidationInfo EditName5="CategoryEdit" Rule="{StaticResource ValidationRuleForField}" />
<helpers:BindingInfo ElementName="UnitPriceEdit" Property="{x:Static dxe:BaseEdit.EditValueProperty}" Value="{Binding EditObject.YbObject.UnitPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<helpers:ValidationInfo EditName6="UnitPriceEdit" Rule="{StaticResource ValidationRuleForField}" />
<helpers:BindingInfo ElementName="RemarkEdit" Property="{x:Static dxe:BaseEdit.EditValueProperty}" Value="{Binding EditObject.YbObject.Remark, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<helpers:ValidationInfo EditName7="RemarkEdit" Rule="{StaticResource ValidationRuleForField}" />
<helpers:BindingInfo ElementName="CreatedEdit" Property="{x:Static dxe:BaseEdit.EditValueProperty}" Value="{Binding EditObject.YbObject.Created, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<helpers:ValidationInfo EditName8="CreatedEdit" Rule="{StaticResource ValidationRuleForField}" />
<helpers:BindingInfo ElementName="LastModifiedEdit" Property="{x:Static dxe:BaseEdit.EditValueProperty}" Value="{Binding EditObject.YbObject.LastModified, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<helpers:ValidationInfo EditName9="LastModifiedEdit" Rule="{StaticResource ValidationRuleForField}" />
清爽、干净的界面层页面后置代码:
namespace YbRapidSolution.Wpf {
public partial class ProductEditView : UserControl {
public ProductEditView()
{
InitializeComponent();
}
}
}
8、其他个性化的功能简直就太多了,而这,仅需你轻轻一点......
附:YbSoftwareFactory 插件开发 SDK 文档 下载
比较遗憾的是没有 DexExpress 11.2.8 的汉化文件,自己汉化的话太麻烦,不知谁能提供一个!