บันทึกนี้ผมแตกประเด็นมาจากบันทึก ASP.NET MVC ว่าด้วยเรื่อง Model แต่เนื้อหาไม่ได้ต่อเนื่องกัน ผมหยิบเอาคำสั่งหน้าตาประหลาดๆ มากเพื่อศึกษาและบันทึกความเข้าใจไว้ นั่นคือ คำสั่งในลักษณะนี้ @Html.DisplayNameFor(x=> x.Name) โครงสร้างคำสั่งแบบนี้จะพบมากขึ้นในโค้ดฝั่ง Microsoft ซึ่งผมเองเคยผ่านการใช้งานโค้ดแบบนี้มาบ้าง เคยถามจากผู้รู้มาบ้าง แต่พอนานวันก็ลืมความหมายไป จึงถือโอกาสทบทวนและบันทึกเป็น km เก็บไว้ว่า

 

เมื่อเอาเมาส์ไปวางเหนือคำสั่ง DisplayNameFor เราจะได้คำอธิบายการใช้มายืดยาว หากไม่คุ้นเคยการใช้งานแบบนี้อาจทำให้งงว่ามันใช้ยังไง คำอธิบายที่แสดงมานั่นคืออะไรบ้าง (MSDN: DisplayNameFor)

  • DisplayNameFor มีหน้าที่แสดงชื่อหรือคำอธิบายของ Model หรือ MvcHtmlString โดยจะใช้ชื่อของ Model หรือชื่อที่ประกาศใน Data Annotation [Display(Name=”label name”)]
  • DisplayNameFor เป็น Extension Method (ฟังก์ชั่นที่ถูกสร้างเพิ่มเติม) ของ Class HtmlHelper ซึ่งในภาพคือ @Html
  • DisplayNameFor มีลักษณะเป็น Generic Method
    • DisplayNameFor<TModel, TValue>
    • TModel และ TValue (หรือชื่ออื่น) ที่อยู่ภายในเครื่องหมาย < > เป็นตัวที่บอกให้รู้ว่านี่คือ Generic Type Parameter
    • <TModel, TValue> เป็นการระบุว่า Method นี้จะมีการใช้ Data Type 2 แบบ ซึ่งผู้นำไปใช้ต้องระบุชัดเจนภายหลัง จากตัวอย่างข้างต้น
      • TModel = HelloMVC.Models.Coffee
      • TValue = string
    • โค้ดการทำงานภายในของ DisplayNameFor จะแทน TModel และ TValue ด้วย DataType ที่กำหนดมา
  • DisplayNameFor ในภาพข้างต้นเป็น Overload แบบ
    public static MvcHtmlString DisplayNameFor<TModel, TValue>(
    	this HtmlHelper<IEnumerable<TModel>> html,
    	Expression<Func<TModel, TValue>> expression
    )

    ในส่วนนี้อาจทำให้เราสับสนว่า Method นี้มี 2 arguments แต่ความเป็นจริง this HtmlHelper<IEnumerable<TModel>> เป็นส่วนของการทำ extension ว่าจะเพิ่มให้กับ Class ที่ชื่อ HtmlHelper เท่านั้น ซึ่ง HtmlHelper เองก็เป็น Generic Class ด้วย

  •  Expression<Func<TModel, TValue>> เป็น argument ของ DisplayNameFor โดยกำหนดให้ส่ง Lambda Expression แบบ Func<in T, out TResult> เข้าไปใน DisplayNameFor นั่นเอง
    • Lambda Expression (MSDN: Expression<TDelegate> Class)
      • รูปแบบของ expressionนี้ คือ x => y
      • เรียกเครื่องหมาย => ว่า Lambda Operator
      • x เป็น input โดยส่วนนี้อาจมี input ได้มากกว่า 1 ตัว จะเขียนเป็น (x,y) => z
      • y เป็น output มักเป็นคำสั่งประมวลผลง่ายๆ เช่น เปรียบเทียบ คำนวนตามสูตรคณิตศาสตร์ แต่สามารถเขียนหลายคำสั่งงานภายใต้ { … } โดยมีคำสั่ง return ก็ได้ แต่ไม่เป็นที่นิยม
      • ในบางบทความจะอธิบายเรื่องนี้เป็น Anonymous Method รูปแบบหนึ่ง
    • Func (MSDN: Func<int T, out TResult>)
      • Func เป็น Delegate ฟังก์ชั่นรูปแบบหนึ่ง และมีการใช้ Generic ด้วย
        public delegate TResult Func<in T, out TResult>(
        	T arg
        )
      • Func ในรูปแบบนี้พอจะอธิบายได้ว่าเป็น Method ที่มีเป็นตัวแปรแบบ T เป็น input และมีค่าแบบ TResult เป็น output
      • รูปแบบของ Func จะมี Overload มากมาย ตั้งแต่ไม่มี input จนถึงมี input หลายตัว แต่ output จะมี 1 เดียวเสมอ หรือพอจะเขียนอธิบายได้ในรูปแบบ Func<in1, in2, … , out>
      • การอธิบายคำสั่งของ Func ไม่จำเป็นต้องอยู่ในรูปแบบ Lambda Expression นั่นคือ อาจเขียนในรูปแบบของ Delegate ทั้งแบบ Explicit หรือ Anonymous ก็ได้ ดูตัวอย่างได้ใน MSDN ที่ระบุไว้ข้างบน
      • สำหรับ @Html.DisplayNameFor(x => x.Name) เป็นการใช้ Func แบบ Lambda สามารถอธิบายได้ว่า
        • มีการส่งค่าจาก @Html มาใส่เป็นในตัวแปร x (สามารถตั้งชื่อตัวแปรเป็นอย่างอื่นได้) ให้เป็น input เข้าสู่ Func<>
        • ในส่วนของ output (หลังเครื่องหมาย =>) จะส่งค่า x.Name ออกมา (ในที่นี่ x เป็น Object ของ Class Coffee จากบันทึกฉบับก่อน)
        • Property ของ Coffee ที่ชื่อว่า Name หรือ x.Name จะถูกนำเป็น input ให้กับ DisplayNameFor เพื่อทำงานต่อไป
        • หากมีการอธิบาย Coffee.Name ด้วย Data Annotation [Display(Name=”label name”)] ก็จะส่งค่าดังกล่าวให้ หากไม่มีก็จะส่งชื่อ Property ว่า Name ทดแทน

ในบันทึกฉบับนี้แม้เราเริ่มจากคำสั่งเพียงชุดเดียว แต่มันมีความรู้มากมายที่ต้องศึกษาทำความเข้าใจ ผมเองคงไม่สามารถศึกษาในรายละเอียดได้ทั้งหมด ทำได้เพียงทำความเข้าใจให้พอรู้และนำไปใช้ได้อย่างเข้าใจ เมื่อไหร่ที่ลืมก็สามารถกลับมาอ่านซ้ำๆ ได้ ก่อนจบผมขอโน้ตหัวเรื่องอื่นๆ ที่พบระหว่างทำบันทึกฉบับนี้ไว้ เพื่อมีโอกาสจะได้ศึกษาต่อไป Anonymous Method แบบ Delegate, Action<> และ Predicate<>

= จบ =

 

ASP.NET MVC: ว่าด้วยเรื่อง Model
รีวิวโปรแกรมสตอรี่บอร์ดออนไลน์

Leave a Comment