2013-05-16 48 views
0

從程序背景來看,我在設計基於菜單的控制檯應用程序和用戶輸入驗證時運行到概念塊。我的目標是顯示一個啓動其他進程的菜單。我想在菜單上將用戶輸入限制爲1,2或3。我需要一個簡單和優雅的用戶驗證技術的c#控制檯應用程序

在程序語言,我會做這樣的事僞代碼:

10 print "Make a choice" 
20 choice = [dataFromKeyboard] 
30 if choice < 4 && choice > 0 
40 then 10 
50 else 60 
60 process valid choices 

不管我怎麼努力,我不能讓這出我的頭在設計OO程序。考慮(簡化爲只包括3個菜單項):

class Menu 
{ 
    public static void Main(String[] args) 
    { 
     DisplayMenu thisdm = new DisplayMenu; 
     int menuChoice = thisdm.displayMenu(); 
     ProcessMenu thispm = new ProcessMenu(); 
     thispm.processMenu(menuChoice); 
    } 
} 

class DisplayMenu 
{ 
    public int displayMenu() 
    { 
     Console.WriteLine("1 - foo3"); 
     Console.WriteLine("2 - foo2"); 
     Console.WriteLine("3 - foo3"); 
     Console.WriteLine("choose"); 
     String choice = Console.ReadLine(); 
     int intChoice = Convert.ToInt32(choice); 
     return intChoice; 
    } 
} 

class ProcessMenu 
{ 
    public void processMenu(int choice) 
    { 
     switch(choice)  
     { 
     case 1: 
      foo1(); 
      break;     
     case 2:    
      foo2(); 
      break; 
     case 3:    
      foo3();; 
      break;   
     default:    
      Console.WriteLine("Invalid selection. Please select 1, 2, or 3.");    
      break;  
     } 
    } 
} 

所以這裏是我卡住的地方。我無法用一種簡單而優雅的方式來包裝我的頭,以驗證我的用戶輸入來自OO而不是程序立場。

假設我在DisplayMenu中進行驗證,我將在輸入讀取後進行驗證。但如果事實證明無效,我如何重新詢問有效的輸入,因爲我已經從Main調用了displayMenu方法?

我一直在玩while循環了大約一個小時,這樣的事情:

intChoice = 0; 
[print the menu] 
while ((intChoice<1) || (intChoice>3)) 
Console.WriteLine("Please make a valid choice from the menu"); 
choice = Console.ReadLine(); 
etc. 

,但似乎無法找到甜蜜點,我可以控制用戶輸入。

我懷疑這是因爲我想要程序化,而不是面向對象。任何人有任何提示或意見,以幫助我包圍我的頭?

+1

考慮將您的班級轉爲90度,並使用{Display/Process/Status}而不是ProcessMenu/DisplayMenu類將班級分爲'MenuItem'。 –

回答

0

讓你的processMenu函數返回某種指標。你可以使用例外來代替,但這太過分了。

public bool processMenu(int choice) 
{ 
    .... 
} 

如果選擇是可以接受的,則返回true,否則返回false。然後:

public static void Main(String[] args) 
{ 
    DisplayMenu thisdm = new DisplayMenu; 
    ProcessMenu thispm = new ProcessMenu(); 

    int menuChoice; 

    do { 
     menuChoice = thisdm.displayMenu(); 
    } while(!thispm.processMenu(menuChoice)); 
} 
0

您應該改變方式。不管怎樣,對於同你的問題,這個作品出來:

DisplayMenu thisdm = new DisplayMenu(); 

int menuChoice = -1; 

while (menuChoice < 1 || menuChoice > 3) 
{ 
    Console.WriteLine("enter valid choice"); 
    menuChoice = thisdm.displayMenu(); 
} 

ProcessMenu thispm = new ProcessMenu(); 
thispm.processMenu(menuChoice); 
0

的代碼,如:

class Program 
{ 
    static void Main(string[] args) 
    { 
     DisplayMenu thisdm = new DisplayMenu(); 
     ProcessMenu thispm = new ProcessMenu(); 

     thisdm.displayMenu(); 
     int menuChoice = thispm.GetChoice(); 
     thispm.processMenu(menuChoice); 

     Console.Read(); 
    } 

} 

class DisplayMenu 
{ 
    public void displayMenu() 
    { 
     Console.WriteLine("1 - foo3"); 
     Console.WriteLine("2 - foo2"); 
     Console.WriteLine("3 - foo3"); 
     Console.WriteLine("choose"); 

    } 
} 

class ProcessMenu 
{ 
    public int GetChoice() 
    { 
     String choice = Console.ReadLine(); 
     int intChoice = Convert.ToInt32(choice); 

     while (!Validate(intChoice)) 
     { 
      Console.WriteLine("Invalid selection. Please select 1, 2, or 3."); 
      choice = Console.ReadLine(); 
      intChoice = Convert.ToInt32(choice); 
     } 

     return intChoice; 
    } 

    public void processMenu(int choice) 
    { 

     switch (choice) 
     { 
      case 1: 
       //foo1(); 
       break; 
      case 2: 
       //foo2(); 
       break; 
      case 3: 
       //foo3(); ; 
       break; 
      default: 
       //Console.WriteLine("Invalid selection. Please select 1, 2, or 3."); 
       break; 
     } 
    } 

    private int[] forChoices=new int[]{1,2,3}; 

    private bool Validate(int choice) 
    { 
     if(forChoices.Contains(choice)) 
     { 
      return true; 
     } 

     return false; 
    } 
} 
+0

快速範圍問題。對於程序流,數組是否實例化爲所有方法的PRIOR,因爲它在所有方法的外部?或者該語句是否需要進入INSIDE的「驗證」方法?後者是我如何做到這一點,所以我很好奇爲什麼這個作品......謝謝。 – dwwilson66

+0

對不起,我不清楚你的困惑。 – Nate

1

拓展上的‘打開你的類90度’@AlexeiLevenkov的建議下,我更進一步,創造了「模塊化」控制檯應用程序的這個例子:

class Program 
{ 
    static void Main(string[] args) 
    { 
     //Retrieve all Module types in the current Assembly. 
     var moduletypes = Assembly.GetExecutingAssembly() 
            .GetTypes() 
            .Where(x => x.IsSubclassOf(typeof(ConsoleModule))); 

     //Create an instance of each module 
     var modules = moduletypes.Select(Activator.CreateInstance) 
           .OfType<ConsoleModule>() 
           .OrderBy(x => x.Id) 
           .ToList(); 


     int SelectedOption = -1; 

     while (SelectedOption != 0) 
     { 
      //Show Main Menu  
      Console.Clear(); 
      Console.WriteLine("Please Select An Option:\n"); 
      modules.ForEach(x => Console.WriteLine(string.Format("{0} - {1}", x.Id, x.DisplayName))); 
      Console.WriteLine("0 - Exit\n"); 
      int.TryParse(Console.ReadLine(), out SelectedOption); 

      //Find Module by Id based on user input 
      var module = modules.FirstOrDefault(x => x.Id == SelectedOption); 

      if (module != null) 
      { 
       //Execute Module 
       Console.Clear(); 
       module.Execute(); 
       Console.WriteLine("Press Enter to Continue..."); 
       Console.ReadLine(); 
      } 
     } 
    } 

ConsoleModule類:

public abstract class ConsoleModule 
{ 
    public int Id { get; set; } 

    public string DisplayName { get; set; } 

    public abstract void Execute(); 

} 

一些樣本模塊:

public class EnterUserNameModule : ConsoleModule 
{ 
    public EnterUserNameModule() 
    { 
     Id = 2; 
     DisplayName = "User Name"; 
    } 

    public static string UserName { get; set; } 

    public override void Execute() 
    { 
     Console.WriteLine("Please Enter Your Name: "); 
     UserName = Console.ReadLine(); 
    } 
} 

public class HelloWorldModule: ConsoleModule 
{ 
    public HelloWorldModule() 
    { 
     Id = 1; 
     DisplayName = "Hello, World!"; 
    } 

    public override void Execute() 
    { 
     Console.WriteLine("Hello, " + (EnterUserNameModule.UserName ?? "World") + "!"); 
    } 
} 

public class SumModule: ConsoleModule 
{ 
    public SumModule() 
    { 
     Id = 3; 
     DisplayName = "Sum"; 
    } 

    public override void Execute() 
    { 
     int number = 0; 
     Console.Write("Enter A Number: "); 
     if (int.TryParse(Console.ReadLine(), out number)) 
      Console.WriteLine("Your number plus 10 is: " + (number + 10)); 
     else 
      Console.WriteLine("Could not read your number."); 
    } 
} 

結果:

enter image description here

它採用反射的一點點地找到所有類型在當前彙編從ConsoleModule推導,然後顯示一個菜單中包含所有這些選項(實際上屬於此類中的屬性),並在選擇了相應選項時調用Execute()方法。更多地面向OO思維方式。

相關問題