SCSF 系列:利用 Smart Client Software Factory 实现 StopLight (Step By Step)

StopLight Unity QuickStart 中包含的实例,用于展示依赖注入,同时使用了 MVP 模式,本文演示将 StopLight 移植到 SCSF ,本篇及以后的几篇文章会依据 StopLight 实例来详细说明 SCSF 的依赖注入,MVP 模式和面向对象的设计原则。StopLight 的设计当然还不完美,但通过它我们可以体会到面向对象设计的和谐和优雅。

一:需求

依次显示绿、黄、红三种颜色,各种颜色的现实时间可以用户手工输入,用户也可以手动强制显示下一个颜色。将显示信息记入日志。

运行界面:

StopLight-Form1     StopLight-Form2

二:简单设计(以后部分会详细讨论为什么这样设计)

1 StoplightViewStopLightForm

具体的现实窗体,提供用户操作接口。

责任:

1.1 实现IStoplightView接口

public partial class StopLightView : UserControl, IStopLightView

1.2 提供事件处理器声明及辅助的事件触发器

public event PropertyChangedEventHandler PropertyChanged;

1.3 指定Presenter

[Dependency]

public StoplightPresenter Presenter

1.4 触发响应事件

RaisePropertyChanged(StoplightViewProperties.RedDuration);

1.5 通过ErrorProvider提示用户输入错误

errorProvider.SetError(controlsByName[propertyName], errorMessage);

2 IStoplightView

定义每个具体的StoplightView都应该提供的接口,继承自INotifyPropertyChanged

责任:

2.1 当前颜色

Color CurrentColor { get; set; }

2.2 每种颜色的显示时间

string GreenDuration { get; set; }

string YellowDuration { get; set; }

string RedDuration { get; set; }

2.3 设置错误信息

void SetError(string propertyName, string errorMessage);

2.4 相应的事件处理器

event EventHandler UpdateClicked;

event EventHandler ForceChangeClicked;

3 StoplightPresenter

实现了MVP模式中的Presenter角色。

责任:

3.1 设置Presenter对于的View

public void SetView(IStoplightView view)

3.2 注册View的事件处理程序

view.PropertyChanged += OnViewPropertyChanged;

view.UpdateClicked += OnViewUpdateClicked;

view.ForceChangeClicked += OnViewForceChangeClicked;

3.2 定义View的事件处理程序

View获取需要的信息,通过IStoplightView接口

更新View,通过IStoplightView接口

ServiceInterfaces层(StopLight.Interface项目)提供服务接口,体现面向接口编程,ServiceImplementations层(StopLight项目)实现具体的接口。接口定义是唯一的,但对接口的实现是不限的。Presenter依赖于抽象的接口而不是具体的服务实现,这样为以后更改具体的服务实现提供了方便。

Logic层(StopLight项目,放在服务中)负责具体的业务逻辑并记录日志。

Stoplight

获取当前颜色:

public StoplightColors CurrentColor

切换到下一个颜色:

public void Next()

StoplightSchedule

根据时间或者用户强制调度颜色。

开始定时器:

public void Start()

更改显示间隔:

public void Update(TimeSpan green, TimeSpan yellow, TimeSpan red)

强制改变:

public void ForceChange()

三、利用 Smart Client Software Factory 实现

利用第一篇中的介绍建立框架,建立一个新的解决方案文件夹 StopLight ,并利用 Smart Client Factory 的 Package Guidance 功能建立一个包含接口层的 Business Module 。项目结构如下:

StopLight-结构

这时 Shell 项目下的 ProfileCatalog.xml 文件自动更新,添加了对 StopLight.dll 的引用:

1  < SolutionProfile xmlns ="http://schemas.microsoft.com/pag/cab-profile/2.0" >
2    < Section Name ="Layout" >
3      < Modules >
4        < ModuleInfo AssemblyFile ="Infrastructure.Layout.dll"   />
5      </ Modules >
6    </ Section >
7    < Section Name ="Services" >
8      < Dependencies >
9        < Dependency Name ="Layout"   />
10      </ Dependencies >
11      < Modules >
12        < ModuleInfo AssemblyFile ="Infrastructure.Module.dll"   />
13      </ Modules >
14    </ Section >
15    < Section Name ="Apps" >
16      < Dependencies >
17        < Dependency Name ="Layout"   />
18        < Dependency Name ="Services"   />
19      </ Dependencies >
20      < Modules >
21        < ModuleInfo AssemblyFile ="StopLight.dll"   />   <!-- 注意 -->
22      </ Modules >
23    </ Section >
24  </ SolutionProfile >

 

在 View 文件夹上点右键,通过 Add View With Presenter 建立 StopLightView :

addView   Add-StopLight-MVP

生成如下 View 相关文件:

StopLight-MVP

随后我们在 StopLight 项目下的 ModuleController 类的  private void AddViews() 方法中添加:

this .ShowViewInWorkspace < StopLightView > (WorkspaceNames.LayoutWorkspace);

运行程序就可以将 StopLightView 显示在 LayoutWorkspace 上了,不过这时 StopLightView  还是个空控件。

接下来我们设计 StopLightView 界面,并实现 IStopLightView  接口的方法和事件。

// -----------------------------------------------------------------------
// <copyright file="Stoplight.cs" company="FLYabroad Enterprises">
//      Copyright (c) FLYabroad. All rights reserved.
// </copyright>
// <author>FLYabroad( http://www.flyabroad111.com )</author>
// -----------------------------------------------------------------------
namespace SmartClient系列.StopLight
{
   
/**//// <summary>
   
/// View 一般继承自 UserControl ,并且实现对于的接口
   
/// </summary>
   
/// <remarks>
   
/// 实现 IStopLightView 接口,提供接口允许外部获取和设置界面上的控件值,设置错误提示,触发相关事件
   
/// </remarks>

    public partial class StopLightView : UserControl, IStopLightView
   
{
       
public StopLightView()
       
{
            InitializeComponent();
        }


       
/**//// <summary>
       
/// 在 View 加载时允许 Presenter 注入适当的操作。开发者可以在 Presenter 中重写 OnViewReady() 介入视图加载过程。
       
/// </summary>
       
/// <param name="e"></param>

        protected override void OnLoad(EventArgs e)
       
{
            _presenter.OnViewReady();
           
base.OnLoad(e);
        }


       
IStoplightView Members#region IStoplightView Members

       
/**//// <summary>
       
/// 当前颜色改变时,触发 PropertyChanged 事件
       
/// </summary>

        public Color CurrentColor
       
{
           
get { return stopLightPanel.BackColor; }
           
set
           
{
                stopLightPanel.BackColor
= value;
                RaisePropertyChanged(StoplightViewProperties.CurrentColor);
            }

        }


       
/**//// <summary>
       
/// 获取或设置绿色持续时间 GreenDuration
       
/// 当 GreenDuration 改变时,触发 PropertyChanged 事件
       
/// </summary>

        public string GreenDuration
       
{
           
get { return greenDurationTextBox.Text; }
           
set
           
{
                greenDurationTextBox.Text
= value;
                RaisePropertyChanged(StoplightViewProperties.GreenDuration);
            }

        }


       
/**//// <summary>
       
/// 获取或设置黄色持续时间 YellowDuration
       
/// 当前 YellowDuration 改变时,触发 PropertyChanged 事件
       
/// </summary>

        public string YellowDuration
       
{
           
get { return yellowDurationTextBox.Text; }
           
set
           
{
                yellowDurationTextBox.Text
= value;
                RaisePropertyChanged(StoplightViewProperties.YellowDuration);
            }

        }


       
/**//// <summary>
       
/// 获取或设置红色持续时间 RedDuration
       
/// 当前 RedDuration 改变时,触发 PropertyChanged 事件
       
/// </summary>

        public string RedDuration
       
{
           
get { return redDurationTextBox.Text; }
           
set
           
{
                redDurationTextBox.Text
= value;
                RaisePropertyChanged(StoplightViewProperties.RedDuration);
            }

        }


       
/**//// <summary>
       
/// 当点击 update schedule 按钮时触发,更改三种颜色的持续时间
       
/// 在 Presenter 的 OnViewSet() 方法中注册
       
/// </summary>

        public event EventHandler UpdateClicked;

       
/**//// <summary>
       
/// 当点击强制更改到下一颜色时触发
       
/// 在 Presenter 的 OnViewSet() 方法中注册
       
/// </summary>

        public event EventHandler ForceChangeClicked;

       
/**//// <summary>
       
/// 通过 ErrorProvider 给对应控件设置错误提示
       
/// Presenter 在处理属性更改事件时调用
       
/// </summary>
       
/// <param name="propertyName"></param>
       
/// <param name="errorMessage"></param>

        public void SetError(string propertyName, string errorMessage)
       
{
            Dictionary
<string, Control> controlsByName = new Dictionary<string, Control>();
            controlsByName.Add(StoplightViewProperties.GreenDuration, greenDurationTextBox);
            controlsByName.Add(StoplightViewProperties.YellowDuration, yellowDurationTextBox);
            controlsByName.Add(StoplightViewProperties.RedDuration, redDurationTextBox);


           
if (controlsByName.ContainsKey(propertyName))
           
{
                errorProvider.SetError(controlsByName[propertyName], errorMessage);
            }

        }


       
#endregion


       
INotifyPropertyChanged Members#region INotifyPropertyChanged Members

       
/**//// <summary>
       
/// 控件属性更改时触发
       
/// 在 Presenter 的 OnViewSet() 方法中注册
       
/// </summary>

        public event PropertyChangedEventHandler PropertyChanged;

       
#endregion


       
// Event firing helpers

       
protected virtual void RaisePropertyChanged(string propertyName)
       
{
            PropertyChangedEventHandler handlers
= PropertyChanged;
           
if (handlers != null)
           
{
                handlers(
this, new PropertyChangedEventArgs(propertyName));
            }

        }


       
protected virtual void RaiseUpdateClicked()
       
{
            EventHandler handlers
= UpdateClicked;
           
if (handlers != null)
           
{
                handlers(
this, EventArgs.Empty);
            }

        }


       
protected virtual void RaiseForceChangeClicked()
       
{
            EventHandler handlers
= ForceChangeClicked;
           
if (handlers != null)
           
{
                handlers(
this, EventArgs.Empty);
            }

        }


       
private void updateScheduleButton_Click(object sender, EventArgs e)
       
{
            RaiseUpdateClicked();
        }



       
private void forceChangeButton_Click(object sender, EventArgs e)
       
{
            RaiseForceChangeClicked();
        }

    }

}

这时运行就有效果了,但没有任何逻辑,灯也不亮,也不会变色。

接下来添加业务逻辑和服务,首先在 StopLight.Interface 项目中添加两个接口:

1  namespace SmartClient系列.StopLight.Interface.Services
2  {
3      public   interface ILogger
4      {
5          void Write( string message);
6      }
7  }

 

1  namespace SmartClient系列.StopLight.Interface.Services
2  {
3      public   interface IStoplightTimer
4      {
5          TimeSpan Duration { get ; set ; }
6          void Start();
7          event EventHandler Expired;
8      }
9  }


然后在 StopLight 项目的 Services 文件夹中实现这些服务还有 StopLight 的业务逻辑:

代码略,需要的可以下载文后提供的整个项目源代码。

现在形成的项目文件结构如下:

StopLight-SCSF-files

现在我们要做的工作是在 ModuleController 中的 AddServices() 方法中添加服务:

        // ModuleController 类,用于在模块加载时添加服务
        private   void AddServices()
       
{
           
//TODO: add services provided by the Module. See: Add or AddNew method in
            WorkItem.Services.AddNew<RealTimeTimer, IStoplightTimer>();
            WorkItem.Services.AddNew
<TraceLogger, ILogger>();
        }

至此,基于 StopLight 的项目完成,后面会以该项目为范例介绍 Smart Client Software Factory 中的 MVP 。

基于 SCSF 的 StopLight 源码下载: http://files.cnblogs.com/flyabroad/StopLight-SCSF.7z
基于 Unity 的 StopLight 源码下载: http://files.cnblogs.com/flyabroad/StopLight-unity.7z

转载于:https://www.cnblogs.com/flyabroad/archive/2008/06/18/1224581.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值