65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 XAF 完成工作 - 第 1 部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.14/5 (7投票s)

2011 年 1 月 12 日

CPOL

4分钟阅读

viewsIcon

114536

downloadIcon

899

eXpressApp Framework (XAF) 教程

引言

如果开发一个相当复杂的应用程序变得非常容易,就像创建几个类然后就可以收工一样,会怎么样?这需要付出代价,但我们都知道天下没有免费的午餐。

好消息是,该解决方案仅包含 63 行代码。事实上,这正是我真正想告诉你的,用最少的工作量完成任务。

我们只需要创建一些域对象类,无需编写 Windows Forms 或 ASP.NET 代码,仍然可以获得功能齐全的 Windows Forms 和 ASP.NET 应用程序。

XAFSmartBooking.png

XAF 来自 DevExpress,是一个框架,使我们能够以最少的开发工作量创建各种应用程序。开箱即用,它提供了许多在开发业务线 (LOB) 应用程序时通常需要的功能。XAF 利用了 DevExpress 的 .NET 组件和 XPO - 他们的对象关系映射 (ORM) 解决方案。

XAFSmartBookingWeb.png

要求

您可以通过 DXperience Universal Subscription 获得 XAF。该产品也有免费试用版。

创建解决方案

使用 Visual Studio 的“新建项目”对话框,以通常的方式创建一个新的基于 XAF 的解决方案。

01-NewProject.png

通过选择“应用程序解决方案”,我们可以得到一个包含 Windows Forms 和 Web 应用程序的解决方案。我认为这很棒,初始解决方案看起来是这样的:

02-SolutionAfterNewProject.png

此时,我们需要为 Windows Forms 项目 `XAFSmartBooking.Win` 打开 `app.config` 文件,为 Web 应用程序项目 `XAFSmartBooking.Web` 打开 `Web.Config` 文件。取消注释我们想要的连接字符串,然后保存并构建解决方案。

现在我们有了一个 Windows Forms 应用程序

03-InitialWindowsForms.png

以及一个 Web 应用程序

04-InitialWeb.png

很高兴从一开始就内置了用户管理功能,而且无需编写任何代码。

创建域对象

由于我们正在处理一个预订应用程序,我们需要预订某些东西,如果你愿意,可以称之为可预订对象。右键单击 `XAFSmartBooking.Module` 项目,然后选择“添加”->“新项”。

05-BookableAddNewItem.png

我们创建一个名为 `Bookable` 的新域对象,这将是我们可预订对象的 `abstract` 基类。起初,我想能够预订建筑物、房间和车辆。所以我们只是使用相同的过程添加所需的类型,从而形成一个简单的层次结构。

06-BookableTypesClassDiagram.png

代码

`Bookable` 是我们的基域对象实体,它继承自 `BaseObject`,这是所有 XAF 域对象都继承的预定义类。我们定义了一个 `string` 属性“`Name`”,并为其添加了 `[Size(255)]` 属性定义。`Size` 属性用于声明底层数据存储中字段的大小。

public abstract class Bookable : BaseObject
    {
        private string name;

        public Bookable(Session session)
            : base(session)
        { }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        [Size(255)]
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                SetPropertyValue("Name", ref name, value);
            }
        }
    }

`Facility` 是 `Building` 和 `Room` 的共同基类。它还公开了一个 `PhoneNumber` 类型的属性,这是 XAF 业务类库中的众多预定义类之一。

在构造时,如果我们的域对象不在加载状态,我们就会创建一个 `PhoneNumber` 类的新实例。如果实体已存在于数据存储中,并且构造函数在加载操作期间被调用,那么该域对象就处于加载状态。

为了方便在保存 `Facility` 对象时保存 `phonenumber`,我们重写了 `OnSave` 方法,并保存了电话号码。

`[ExpandObjectMembers(ExpandObjectMembers.InDetailView)]` 属性声明强制展开 `PhoneNumber` 上定义的属性,用于 `Facility` 对象的详细视图。

public abstract class Facility : Bookable
    {
        private PhoneNumber phoneNumber;

        public Facility(Session session)
            : base(session)
        {
            if (!IsLoading)
            {
                phoneNumber = new PhoneNumber(session);
            }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        protected override void OnSaving()
        {
            phoneNumber.Save();
            base.OnSaving();
        }

        [ExpandObjectMembers(ExpandObjectMembers.InDetailView)]
        public PhoneNumber PhoneNumber
        {
            get
            {
                return phoneNumber;
            }
            set
            {
                SetPropertyValue("PhoneNumber", 
                                      ref phoneNumber, value);
            }
        }
    }

`TypeBase` 将用作用于区分各种类型的建筑物、房间和车辆的类的基类。

`[NonPersistent]` 属性确保 XAF,或者更准确地说 XPO,不会为该类型创建表。`Name` 属性将与直接子类的属性存储在同一个表中。`[Indexed(Unique=true)]` 指示 XAF 在用于存储属性的列上创建唯一索引。该列对于子类是唯一的,而不是对于 `TypeBase` 类的实例。

    [NonPersistent]
    public abstract class TypeBase : BaseObject
    {
        private string name;

        public TypeBase(Session session)
            : base(session)
        { }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        [Size(255)]
        [Indexed(Unique=true)]
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                SetPropertyValue("Name", ref name, value);
            }
        }
    }

`BuildingType` 是用于定义 `Bookable` 子类判别符的三类之一,另外两类是 `RoomType` 和 `VehicleType`。

`[Association("Building-BuildingType", typeof(Building))]` 定义了 `BuildingType` 和 `Building` 之间的一对多关系的“一”侧。`Buildings` 属性返回关联的 `Building` 对象作为集合。

    [DefaultClassOptions]
    [NavigationItem("Facilities")]
    [ImageName("BO_Category")]
    public class BuildingType : TypeBase
    {
        public BuildingType(Session session)
            : base(session)
        {}
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        [Association("Building-BuildingType", typeof(Building))]
        public XPCollection Buildings
        {
            get
            {
                return GetCollection("Buildings");
            }
        }
    }

这是我们的 `Building` 类。它包括与 `BuildingType` 类的一对多关联的“多”侧,并且还使用了 XAF 业务类库中的另一个预定义类 `Address`。

    [DefaultClassOptions]
    [NavigationItem("Facilities")]
    [ImageName("BO_Organization")]
    public class Building : Facility
    {
        private BuildingType type;
        private Address address;

        public Building(Session session)
            : base(session)
        {
            if (!IsLoading)
            {
                address = new Address(session);
            }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        protected override void OnSaving()
        {
            address.Save();
            base.OnSaving();
        }

        [Association("Building-BuildingType", typeof(BuildingType))]
        public BuildingType Type
        {
            get
            {
                return type;
            }
            set
            {
                SetPropertyValue<buildingtype>("Type", 
                                 ref type, value);
            }
        }

        [ExpandObjectMembers(ExpandObjectMembers.InDetailView)]
        public Address Address
        {
            get
            {
                return address;
            }
            set
            {
               SetPropertyValue<address>("Address", ref address, value);
            }
        }
    }

结论

这再简单不过了。仅用 63 行代码,我们就创建了一个可以自行维护数据存储的解决方案。XAF 支持流行的数据库管理系统,如 Microsoft SQL Server、IBM DB2、Oracle RDBMS 等。

作为额外的奖励,我们同时拥有一个 Windows Forms 应用程序和一个 ASP.NET 应用程序。

本系列的下一部分将添加对预订的支持,而且看起来也会很棒。

历史

  • 2011 年 1 月 12 日 - 首次发布
  • 2011 年 1 月 14 日 - 在页面顶部添加了 XAF 链接
© . All rights reserved.