CAB与OOAD(上)续三
1 练习
1.1 练习一
1.1.1 目的
了解Composite UI Application Block的基本应用
理解容器、WorkItem、Shell的概念
1.1.2 步骤
1、新建Windows应用程序项目 CustomerDemo。引用Microsoft.Practices.CompositeUI.dll、Microsoft.Practices.CompositeUI.WinForms.dll、Microsoft.Practices.ObjectBuilder.dll、WinFormsUI.Docking.dll、DSS.CompositeUI.WinForms.dll项。
2、更改Form1类为CustomerForm类。在工具箱的选择项中添加对DSS.CompositeUI.WinForms.dll库的引用。将控件DockWorkspace添加到CustomerForm上,设置其属性Name为MainWorkspace,DocumentStyle为DockingWindow,Dock为Fill。
3、新建CustomersWorkItem类,在该类中引用命名空间Microsoft.Practices.CompositeUI,使CustomersWorkItem为WorkItem的子类。
4、新建MainApplication类,在该类中引用命名空间Microsoft.Practices.CompositeUI、Microsoft.Practices.CompositeUI.WinForms,使其继承自FormShellApplication,使MainApplication的Shell为CustomerForm,主WorkItem为CustomersWorkItem。如下所示:
class MainApplication:FormShellApplication<CustomersWorkItem,CustomerForm>
5、更改Program类Main方法的内容:new MainApplication().Run();F5运行。
1.2 练习二
1.2.1 目的
了解Module的设计
了解如何向壳中添加自定义模型
1.2.2 步骤
1、在练习一的基础上,新建Windows控件库CustomerModule,删除掉原有的类UserControl1.cs。添加Microsoft.Practices.CompositeUI.dll、Microsoft.Practices.CompositeUI.WinForms.dll、Microsoft.Practices.ObjectBuilder.dll、DSS.CompositeUI.WinForms.dll、WinFormsUI.Docking.dll项
2、参照案例中的View。添加两个窗体CustomerListForm、CustomerDetailForm两个窗体,引用WinFormsUI、Microsoft.Practices.CompositeUI、Microsoft.Practices.ObjectBuilder命名空间,使他们都继承自DockContent类。
为CustomerListForm添加ListBox控件,设置ListBox控件的属性Name为customerList,Dock为Full。将CustomerListForm的属性ShowHint为DockLeft。
为CustomerDetailForm添加四个标签和四个文本框。
3、添加新类CustomerWorkItem,声明其为Public的,添加对Microsoft.Practices.CompositeUI和Microsoft.Practices.CompositeUI.WinForms、Microsoft.Practices.CompositeUI.SmartParts命名空间的引用,使其作为WorkItem的子类。在CustomerWorkItem中,添加customerListForm、customerDetailForm两个窗体的实体:
CustomerListForm customerListForm;
CustomerDetailForm customerDetailForm;
重写OnRunStarted方法:
protected override void OnRunStarted()
{
base.OnRunStarted();
IWorkspace workSpace = Workspaces["MainWorkspace"];
customerListForm=this.SmartParts.AddNew<CustomerListForm>();
customerDetailForm = this.SmartParts.AddNew<CustomerDetailForm>();
workSpace.Show(customerListForm);
workSpace.Show(customerDetailForm);
}
通过CustomerWorkItem组织窗体的显示。
4、添加新类CustomerModule,声明其为Public的,添加对Microsoft.Practices.CompositeUI和Microsoft.Practices.CompositeUI.WinForms命名空间的引用。使其作为ModuleInit的子类。在CustomerModule类中,添加mainWorkItem成员从容器中获取主WorkItem。
private WorkItem mainWorkItem;
[ServiceDependency]
public WorkItem MainWorkItem {
set { mainWorkItem = value; }
}
重写load方法:
public override void Load()
{
base.Load();
CustomerWorkItem customerWorkItem=mainWorkItem.Items.AddNew<CustomerWorkItem>();
customerWorkItem.Run();
}
当Module被调用时,Load方法被执行。
5、编译项目CustomerModule,生成CustomerModule.Dll程序集,将其Copy到CustomerDemo项目的生成目录下。或者更改CustomerModule的生成目录为CustomerDemo项目的生成目录。
6、在CustomerDemo项目下添加ProfileCatalog.xml文件。设置该文件的复制到输出目录为始终复制,并使CustomerModule.Dll作为模块集合的一部分:
<?xml version="1.0" encoding="utf-8" ?>
<SolutionProfile xmlns="http://schemas.microsoft.com/pag/cab-profile">
<Modules>
<ModuleInfo AssemblyFile="CustomerModule.dll"/>
</Modules>
</SolutionProfile>
7、编译解决方案,F5运行。
1.3 练习三
1.3.1 目的
了解View、Controller、Model的概念
1.3.2 步骤
1、在CustomerModule下添加Model中的实体类:Customer:
public class Customer
{
private string firstName;
private string lastName;
private string address;
public Customer(string firstName, string lastName, string address, string comments)
{
this.firstName = firstName;
this.lastName = lastName;
this.address = address;
}
public string FullName{get { return firstName + " " + lastName; }}
public string LastName {
get { return lastName; }
set { lastName = value; }
}
public string FirstName {
get { return firstName; }
set { firstName = value; }
}
public string Address {
get { return address; }
set { address = value; }
}
}
2、为CustomerDetailForm窗体添加BindingSource控件,设计其属性Name为customerBindingSource。设置其DataSource属性,在弹出的对话框中选择“添加项目数据源”:
选择对象,点击下一步,将对象设置为Customer类。同时分别设置每个TextBox的DataBindings的Text属性为Customer类的Address、LastName、FirstName和FullName属性。
为CustomerDetailForm添加Customer属性:
private Customer customer;
public Customer Customer {
get { return customer; }
set {
if (this.customer != value) {
customer = value;
this.CustomerBindingSource.Clear();
this.CustomerBindingSource.Add(value);
}
}
}
3、为CustomerWorkItem类添加ShowCustomerDetails方法
public void ShowCustomerDetails(Customer customer)
{
customerDetailForm.Customer = customer;
}
4、添加分析类CustomerController,引用Microsoft.Practices.CompositeUI命名空间。使其继承自Controller:
public class CustomerController : Controller
同时添加Controller所需要具有的两个职能:显示客户列表GetCustomers,显示客户详细信息ShowCustomerDetails。
显示客户列表GetCustomers:
public List<Customer> GetCustomers()
{
List<Customer> customers = new List<Customer>();
customers.Add(new Customer("Jesper", "Aaberg", "One Microsoft Way, Redmond WA 98052", "CAB Rocks!"));
customers.Add(new Customer("Martin", "Bankov", "
customers.Add(new Customer("Shu", "Ito", "
customers.Add(new Customer("Kim", "Ralls", "
customers.Add(new Customer("John", "Kane", "
return customers;
}
显示客户详细信息ShowCustomerDetails。
public void ShowCustomerDetails(Customer customer)
{
customerWorkItem.ShowCustomerDetails(customer);
}
customerWorkItem是CustomerModule中CustomerWorkItem的实例。该实例来自于CompositeUI Application Block的容器。
private CustomerWorkItem customerWorkItem;
[ServiceDependency]
public CustomerWorkItem CustomerWorkItem
{
set { customerWorkItem = value; }
}
将上述代码添加到CustomerController中,customerWorkItem会自动从容器中直接获取。
5、为CustomerListForm类添加CustomerController的实例:
private CustomerController controller;
[CreateNew]
public CustomerController Controller {
set { controller = value; }
}
当窗体加载的时候,我们需要将客户的信息添加到CustomerListForm中:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
customerList.DataSource = controller.GetCustomers();
customerList.DisplayMember = "FullName";
customerList.SelectedIndexChanged += new EventHandler(customerList_SelectedIndexChanged);
}
同时设置当员工选择不同客户时执行的函数:
void customerList_SelectedIndexChanged(object sender, EventArgs e)
{
controller.ShowCustomerDetails((Customer)this.customerList.SelectedValue);
}
6、F5运行。
1.4 练习四
1.4.1 目的
了解State的用法
1.4.2 步骤
1、为CustomerController添加Customers属性,需要添加System.Windows.Forms命名空间
[State("Customers")]
public List<Customer> customers
{
get { return (List<Customer>)State["Customers"]; }
set
{
try{
if ((value != null) && (State != null))
{
State["Customers"] = value;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace);
}
}
}
更改GetCustomers方法:
public void GetCustomers()
{
customers.Add(new Customer("Jesper", "Aaberg", "One Microsoft Way, Redmond WA 98052", "CAB Rocks!"));
customers.Add(new Customer("Martin", "Bankov", "
customers.Add(new Customer("Shu", "Ito", "
customers.Add(new Customer("Kim", "Ralls", "
customers.Add(new Customer("John", "Kane", "
}
2、为CustomerListForm类添加Customers属性
private List<Customer> customers = null;
[State]
public List<Customer> Customers
{
set { customers = value; }
}
更改CustomerListForm的OnLoad方法
base.OnLoad(e);
controller.GetCustomers();
customerList.DataSource = Customers;
…
3、为CustomerWorkItem的OnRunStarted方法添加代码
State["Customers"] = new List<Customer>();
base.OnRunStarted();
… …
4、F5运行
1.5 练习五
1.5.1 目的
系统结果的解藕
理解在系统中的分布情况
1.5.2 步骤
1、新建一个类库项目DomainModel,将Customer提取出来,成为领域模型专用库。因为领域模型对象需要在客户端和服务器两端移动,所以需要将其标识为可序列化的:
[Serializable]
public class Customer
2、删除CustomerModel中原有的Customer类,添加对DomainModel的引用,在原来需要使用Customer的类中添加对DomainModel的引用。
3、将CustomerController类中GetCustomers方法获取数据的部分提出出来形成服务。新建一个类库项目Interface,添加对DomainModel项目的引用,同时引用DSS.Core.dll。新建ICustomerService接口,声明引用DomainModel命名空间,为ICustomerService接口添加GetCustomers方法声明:
[ServiceInfomation("CustomerSerivice", ServiceType.Infrustructure)]
public interface ICustomerService {
List<Customer> GetCustomers();
}
4、新建类库项目Implement,添加对DomainModel和Interface项目的引用。将class1.cs类更改为CustomerService,声明它对DomainModel和Interface命名空间的引用。使其继承自ICustomerService,完成对GetCustomers方法的实现:
public class CustomerService:ICustomerService
{
public List<Customer> GetCustomers()
{
List<Customer> customers = new List<Customer>();
customers.Add(new Customer("Jesper", "Aaberg", "One Microsoft Way, Redmond WA 98052", "CAB Rocks!"));
customers.Add(new Customer("Martin", "Bankov", "
customers.Add(new Customer("Shu", "Ito", "
customers.Add(new Customer("Kim", "Ralls", "
customers.Add(new Customer("John", "Kane", "
return customers;
}
}
5、为CustomerModel项目添加对Interface项目的引用。为CustomerController类添加Interface命名空间。添加ICustomerService的实例:
private ICustomerService service;
[ServiceDependency]
public ICustomerService Service
{
set { service = value; }
}
更改CustomerController的GetCustomers方法:
public void GetCustomers()
{
Customers.AddRange(service.GetCustomers());
}
6、为CustomerDemo项目中添加App.Config文件,将Interface和Implement两个实现库Copy到CustomerDemo的运行目录下。将这两个库的服务添加到App.Config文件中:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="CompositeUI"
type="Microsoft.Practices.CompositeUI.Configuration.SettingsSection,
Microsoft.Practices.CompositeUI"
allowExeDefinition="MachineToLocalUser" />
</configSections>
<CompositeUI>
<services>
<add serviceType="Interface.ICustomerService, Interface"
instanceType="Implement.CustomerService, Implement"/>
</services>
</CompositeUI>
</configuration>
7、F5运行
练习六
将Implement布署到服务器端,应用骨架运行系统