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

C# 中的简单图书馆目录系统

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.91/5 (9投票s)

2007年11月15日

Ms-RL

2分钟阅读

viewsIcon

71216

downloadIcon

5675

本文描述了一个用 C# 开发的简单图书馆目录系统,可以作为基础。

引言

在本文中,我们将研究由继承和多态性实现的功能。请注意,此应用程序要求您先登录才能开始。 应用程序启动时会创建三个登录,每个用户类型一个

管理用户
登录名:admin
密码:admin
工作人员用户
登录名:staff
密码:staff
学生用户
登录名:student
密码:student

当程序在管理用户菜单下运行时,您可以创建更多用户。

提供的代码中使用了两个继承层次结构,一个代表不同类型的用户,另一个代表不同的目录项。

MenuBuilder 类定义了将显示给用户的每个菜单中的项目。用户管理允许创建不同的用户对象:Admin 用户、Student 用户和 Staff 用户。 逐步描述应用程序如何创建这些对象并获取其属性所需的信息。

#region Catalogue Management Menu

public static void CatalogueManagementMenu(Users.User usr, out ExtendedResult result)
{
    SortedList<string, MenuOption> menu = new SortedList<string, MenuOption>();
    menu.Add("B", new MenuOption("B", "Add new book", new MenuHandler(AddBookHandler)));
    menu.Add("P", new MenuOption("P", "Add new periodical", new MenuHandler(AddPeriodicalHandler)));
    menu.Add("X", new MenuOption("X", "Exit", new MenuHandler(LogoutHandler)));
    result = new ExtendedResult(ResultCode.SubMenu, menu);
}

#endregion

#region User Management Handlers

private static void AddUserHandler(Users.User usr, out ExtendedResult result)
{
    SortedList<string, MenuOption> menu = new SortedList<string, MenuOption>();
    menu.Add("A", new MenuOption("A", "Administrator", new MenuHandler(AdministratorHandler)));
    menu.Add("M", new MenuOption("M", "Staff Member", new MenuHandler(StaffMemberHandler)));
    menu.Add("S", new MenuOption("S", "Student", new MenuHandler(StudentHandler)));
    menu.Add("X", new MenuOption("X", "Go Back", new MenuHandler(GoBackHandler)));

    result = new ExtendedResult(ResultCode.SubMenu, menu);
}

用户的创建是通过调用 AutoPrompt.Create<>() 泛型函数完成的, <> 中指示了特定的用户(Users.Admin、Users.Staff 或 Users.Student)。

Create<>() 函数创建一个新对象(由 'datatype' 表示),然后通过引用将这个新对象传递给 CreateWorker<>() 函数,同时指示它的数据类型 (typeof(datatype))。

public static datatype Create<datatype>() where datatype : new()
{
    datatype dt = new datatype();
    CreateWorker<datatype>(ref dt, typeof(datatype));
    return dt;
}

CreateWorker<>() 函数

  1. 如果指示的数据类型是 object 类型,则立即返回,否则递归调用自身,传递相同的对象,但指示下一个祖先类类型(基类型)。因此,在传递给 CreateWorker 的类型层次结构中,实际上要处理的第一个类型是直接从 object 类型派生的数据类型,然后是下一个子类,依此类推,直到达到原始类型。
  2. 对于当前类型,使用一个 foreach 循环来检查每个 NonPublic(即私有或受保护)的实例成员(即非静态成员)
    1. 如果该类型是 Field(即属性)
      • 尝试检索 AutoPrompt 代码属性,如果没有这样的代码属性,则移至循环 (b) 中标识的下一个成员。
      • 检索在 AutoPrompt 代码属性中指定的提示
      • 根据数据类型(大的 if/else-if 语句),提示用户输入适当的数据,然后将其存储到对象中(fi.SetValue 存储该值)。
private static void CreateWorker<datatype>(ref datatype obj, Type t)
{
    if (t == typeof(object))
    return;
        CreateWorker<datatype>(ref obj, t.BaseType);

        foreach (MemberInfo mi in t.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance))
        {
          if (mi.MemberType == MemberTypes.Field)
            {
              AutoPrompt ap = Attribute.GetCustomAttribute(mi, typeof(AutoPrompt)) as AutoPrompt;
              if (ap == null)
                continue;

        FieldInfo fi = mi as FieldInfo;
        string fieldPrompt = ap.PromptText;

关注点

提供的代码中使用了两个继承层次结构,一个代表不同类型的用户,另一个代表不同的目录项。

历史

  • 2007 年 11 月 16 日
© . All rights reserved.