Introduction
In this article we will be examining the functionality made possible by inheritance and polymorphism. Note that this application requires you to login to begin with. Three logins are created when the application starts, one for each type of user:
- Administrative User
- Login: admin
Password: admin - Staff Member User
- Login: staff
Password: staff - Student User
- Login: student
Password: student
You can create further users when the program is running under the menu for the administrative user.
There are two inheritance hierarchies used within the provided code, a hierarchy representing different types of users, and a separate hierarchy representing different catalog items.
The MenuBuilder class defines what items will appear in each of the menus presented to the user. The User Management allows for different user objects to be created: an Admin user, a Student user, and a Staff user. Describe, step by step, how the application creates these objects and obtains the information required for their attributes.
#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);
}
The creation of a user is done by invoking the AutoPrompt.Create<>() generic function, with the particular user indicated inside the <> (Users.Admin, Users.Staff, or Users.Student).
The Create<>() function creates one of the new objects (represented by 'datatype') then passes this new object by reference to the CreateWorker<>() function along with an indication of its datatype (typeof(datatype)).
public static datatype Create<datatype>() where datatype : new()
{
datatype dt = new datatype();
CreateWorker<datatype>(ref dt, typeof(datatype));
return dt;
}
The CreateWorker<>() function
- Immediately returns if the data type indicated is type object, otherwise recursively calls itself, passing the same object through but instead indicating the next ancestor class type (base type). Thus, in the hierarchy of types passed to CreateWorker, the first type that will actually be processed is the data type that is directly derived from type object, then the next child class, and so on, until the original type is reached.
- For the current type, a foreach loop is used to examine each of the NonPublic (i.e., private or protected), Insance members (i.e., non-static members)
- If the type is a Field (i.e., attribute)
- Attempt to retrieve the AutoPrompt code attribute, if there is no such code attribute then move onto the next member identified by the loop at (b) above.
- Retrieve the prompt specified in the AutoPrompt code attribute
- Depending on the data type (the large if/else-if statement), prompt the user for the appropriate data and then store it into the object (fi.SetValue stores the value).
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;
Points of Interest
There are two inheritance hierarchies used within the provided code, a hierarchy representing different types of users, and a separate hierarchy representing different catalog items.
History