2011-07-19 42 views
4

我目前正在開發一個MVC.NET 3應用程序;我最近參加了一個名爲「Bob叔叔」的Martin課程,這個課程激勵我(羞辱我)努力研究我目前的開發實踐,特別是我的重構習慣。我的控制器中的重構開關語句

所以:我的一些途徑符合:

{控制器}/{行動}/{類型}將被返回

凡類型通常確定的ActionResult的類型,例如:

public class ExportController 
{ 
    public ActionResult Generate(String type, String parameters) 
    { 
     switch (type) 
     { 
      case "csv": 
      //do something 
      case "html": 
      //do something else 
      case "json": 
      //do yet another thing 
     }  
    } 
} 

有沒有人成功地應用了「替換交換與polymorhism」重構到這樣的代碼?這是個好主意嗎?聽聽你使用這種重構的經驗會很棒。

在此先感謝!

回答

3

如果你想在這種情況下用「多態性替換交換機」,你可以創建三個重載的Generate()ActionResult方法。使用custom model binding,使類型參數強類型的枚舉稱爲DATAFORMAT(或其他)。然後你必須:

public ActionResult Generate(DataFormat.CSV, String parameters) 
    { 
    } 

public ActionResult Generate(DataFormat.HTML, String parameters) 
    { 
    } 

public ActionResult Generate(DataFormat.JSON, String parameters) 
    { 
    } 

一旦到了這一點,你可以進一步重構得到重複出你控制器。

+0

嗨戴夫這看起來完全一樣,我正在尋找。感謝提供自定義模型綁定的提示,我認爲它在其他地方也會非常有用。 – iagomartinez

+0

謹慎闡述?如果DataFormat.CSV是一個值,那麼你的方法是無效的C#。 – Kugel

+0

ModelBinder將如何確定哪些重載是正確的? – Kugel

4

我在看它的方式,該控制器動作尖叫自定義操作結果:

public class MyActionResult : ActionResult 
{ 
    public object Model { get; private set; } 

    public MyActionResult(object model) 
    { 
     if (model == null) 
     { 
      throw new ArgumentNullException("Haven't you heard of view models???"); 
     } 
     Model = model; 
    } 

    public override void ExecuteResult(ControllerContext context) 
    { 
     // TODO: You could also use the context.HttpContext.Request.ContentType 
     // instead of this type route parameter 
     var typeValue = context.Controller.ValueProvider.GetValue("type"); 
     var type = typeValue != null ? typeValue.AttemptedValue : null; 
     if (type == null) 
     { 
      throw new ArgumentNullException("Please specify a type"); 
     } 

     var response = context.HttpContext.Response; 
     if (string.Equals("json", type, StringComparison.OrdinalIgnoreCase)) 
     { 
      var serializer = new JavaScriptSerializer(); 
      response.ContentType = "text/json"; 
      response.Write(serializer.Serialize(Model)); 
     } 
     else if (string.Equals("xml", type, StringComparison.OrdinalIgnoreCase)) 
     { 
      var serializer = new XmlSerializer(Model.GetType()); 
      response.ContentType = "text/xml"; 
      serializer.Serialize(response.Output, Model); 
     } 
     else if (string.Equals("csv", type, StringComparison.OrdinalIgnoreCase)) 
     { 
      // TODO: 
     } 
     else 
     { 
      throw new NotImplementedException(
       string.Format(
        "Sorry but \"{0}\" is not a supported. Try again later", 
        type 
       ) 
      ); 
     } 
    } 
} 

然後:

public ActionResult Generate(string parameters) 
{ 
    MyViewModel model = _repository.GetMeTheModel(parameters); 
    return new MyActionResult(model); 
} 

控制器不應該關心如何序列化數據。這不是他的責任。控制器不應該像這樣做任何管道。他應該專注於獲取域模型,將它們映射到查看模型並傳遞這些視圖模型以查看結果。

+0

嗨達林,謝謝你的回答,我喜歡這個事實,'管道'方面優雅地移出控制器。然而 - 嚴格來說,原來的開關並沒有真正被重構 - 它已經被移入了不同的結構:)我可以看到這對於我們在幾個地方是非常有用的,所以謝謝! – iagomartinez