.NET
MVC Design Pattern
▌背景
專案中需要在MVC同一個VIEW上動態依照後端提供的產品規格(View Model)做隱藏/顯示欄位(選項)。 本範例使用Builder設計模式來達到此目的。
|
▌環境
l Windows 7 pro
l IIS Express 7.5
l Visual Studio 2013
update3 (C#)
|
▌實作截圖
l 2 partial view and
each contains single data.
l 3 partial views and
different data.
|
▌實作
▋Model
l Parent
public class Parent
{
[Key]
[DisplayName("代號")]
public String Id { get; set; }
[DisplayName("父母姓名")]
public String Name { get; set; }
}
|
l Child
public class Child
{
[Key]
public String Id { get; set; }
[DisplayName("小孩姓名")]
public String Name {get;set;}
[DisplayName("生日")]
public String Birthday { get; set; }
}
|
l Pet
public class Pet
{
[Key]
public String Id { get; set; }
[DisplayName("寵物")]
public String PetType { get; set; }
}
|
l MyHome
public class MyHome
{
public IEnumerable<Model.Parent> Parents { get; set; }
public IEnumerable< Model.Child> Chidren { get; set; }
public IEnumerable< Model.Pet> Pets { get; set; }
}
|
▋View
l 建立以下View
l _ChildPartial.cshtml
@using
Chapter01.Domain.Model
@model Child
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model =>
model.Name)
</th>
<th>
@Html.DisplayNameFor(model =>
model.Birthday)
</th>
</tr>
@if (Model != null)
{
<tr>
<td>
@Html.DisplayFor(modelItem =>
Model.Name)
</td>
<td>
@Html.DisplayFor(modelItem =>
Model.Birthday)
</td>
</tr>
}
</table>
|
※_ParentPartial &
_PetPartial 兩個Partial View 請如上建立。
l Index.cshtml
主頁面由三個Partial View組成, 且在run-time時由ViewModel的資料來決定顯示與否。
@using
Chapter01.Domain.Model
@model Chapter01.Domain.Model.MyHome
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<div style="background-color:lightblue">
@if (Model.Parents != null)
{
for (int i = 0; i <
Model.Parents.Count(); i++)
{
@Html.Partial("_ParentPartial",
Model.Parents.ToList()[i])
}
}
</div>
<div style="background-color:lightcyan">
@if (Model.Chidren != null)
{
for (int i = 0; i <
Model.Chidren.Count(); i++)
{
@Html.Partial("_ChildPartial",
Model.Chidren.ToList()[i])
}
}
</div>
<div style="background-color:lightgreen">
@if (Model.Pets != null)
{
for (int i = 0; i < Model.Pets.Count();
i++)
{
@Html.Partial("_PetPartial",
Model.Pets.ToList()[i])
}
}
</div>
|
有了View,只要在Controller傳回ViewResult 時塞入model就可以了。 所以我們這邊開始實作Builder的程式碼。
l Builder
public abstract class HomeBuilder<T>
{
/// 建立物件
abstract public T Create();
abstract protected void CreateParent(T myHome);
abstract protected void CreateChild(T myHome);
abstract protected void CreatePet(T myHome);
}
|
l Director
public class HomeBuildDirector : IDisposable
{
private MyHome _myHome;
public HomeBuildDirector(HomeBuilder<MyHome> homeBuilder)
{
this._myHome = homeBuilder.Create();
}
public MyHome Get()
{
return this._myHome;
}
public void Dispose()
{
if (this._myHome != null)
{
this._myHome = null;
}
}
}
|
l ConcreteBuilder
1.
ConcreteBuilder 1
public class PeterHome<T> : HomeBuilder<T> where T : MyHome, new()
{
override public T Create()
{
var peterHome = new T();
this.CreateParent(peterHome);
this.CreateChild(peterHome);
this.CreatePet(peterHome);
return peterHome;
}
override protected void CreateParent(T myHome)
{
var a1 = new Parent()
{
Id = "Peter",
Name = "Peter
Chang"
};
var setA = new List<Parent>() { a1 };
myHome.Parents =
setA.AsEnumerable();
}
override protected void CreateChild(T myHome)
{
myHome.Chidren = null;
}
override protected void CreatePet(T myHome)
{
var c1 = new Pet()
{
PetType = "黃金獵犬"
};
var setC = new List<Pet>() { c1 };
myHome.Pets = setC.AsEnumerable();
}
}
|
2.
ConcreteBuilder 2
public class AnakinHome<T> : HomeBuilder<T> where T : MyHome, new()
{
override public T Create()
{
var anakinHome = new T();
this.CreateParent(anakinHome);
this.CreateChild(anakinHome);
this.CreatePet(anakinHome);
return anakinHome;
}
override protected void CreateParent(T myHome)
{
var a1 = new Parent()
{
Id = "Anakin",
Name = "Anakin
Skywalker"
};
var a2 = new Parent()
{
Id = "Padme",
Name = "Princess
Amidala"
};
var setA = new List<Parent>() { a1, a2 };
myHome.Parents =
setA.AsEnumerable();
}
override protected void CreateChild(T myHome)
{
var b1 = new Child()
{
Name = "Luke
Skywalker",
Birthday = "??"
};
var b2 = new Child()
{
Name = "Leia
Skywalker",
Birthday = "??"
};
var setB = new List<Child>() { b1,b2 };
myHome.Chidren =
setB.AsEnumerable();
}
override protected void CreatePet(T myHome)
{
var c1 = new Pet()
{
PetType = "R2D2"
};
var c2 = new Pet()
{
PetType = "C3PO"
};
var setC = new List<Pet>() { c1,c2 };
myHome.Pets =
setC.AsEnumerable();
}
}
|
3.
如果有需要,可以建立更多ConcreteBuilder class.
▋Controller
l Action
在主程式可決定要用的ConcreteBuilder~
public ActionResult Index()
{
MyHome model = null;
//The builder of Anakin's home
var builder = new Chapter01.Domain.Model.AnakinHome<MyHome>();
//The builder of Peter's home
//var builder =
new Chapter01.Domain.Model.PeterHome<MyHome>();
//Build it!
using (var builderDirector =
new
Chapter01.Domain.Builder.HomeBuildDirector(builder))
{
model = builderDirector.Get();
}
return View(model);
}
|
▋Reference
沒有留言:
張貼留言