我目前正在开发一个MVC.NET 3应用程序;我最近参加了“叔叔鲍勃”马丁的课程,这个课程激励我(让我感到羞耻?)仔细研究我目前的开发实践,特别是我的重构习惯。
所以:我的一些路线符合:
{控制器} / {行动} / {类型}
其中type通常决定要返回的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
}
}
}
有没有人成功地将“使用多态的替换开关”重构为这样的代码?这甚至是个好主意吗?很高兴听到你对这种重构的经历。
提前致谢!
答案 0 :(得分: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);
}
控制器不应该关心如何序列化数据。那不是他的责任。控制器不应该像这样做任何管道。他应该专注于获取领域模型,将它们映射到视图模型并将这些视图模型传递给查看结果。
答案 1 :(得分:3)
如果你想在这种情况下“用多态替换switch”,你可以创建三个重载的Generate()ActionResult方法。使用custom model binding,使Type参数成为一个强类型枚举,称为DataFormat(或其他。)然后你有:
public ActionResult Generate(DataFormat.CSV, String parameters)
{
}
public ActionResult Generate(DataFormat.HTML, String parameters)
{
}
public ActionResult Generate(DataFormat.JSON, String parameters)
{
}
一旦达到这一点,您可以进一步重构以从控制器中重复出现。