Archive

Archive for the ‘DOT NET’ Category

การใช้งาน ADO.NET กับ วิธีปฏิบัติที่เป็นเลิศ [ Best practices ]

ผมครุ่นคิดอยู่นานว่า การใช้งาน Component ต่าง ๆ ใน .NET Framework นั้น จะทำอย่างไร จึงจะสามารถใช้ได้อย่างมีประสิทธิภาพเนื่องจาก document หรือ คู่มือต่าง ๆ ที่เราพอหาได้นั้นจะเป็นคู่มือแนะนำการใช้งาน กว่าเราจะเข้าใจการทำงานอย่างถ่องแท้และสามารถเลือกการปฏิบัติในการใช้งานด้วยตัวเองได้ดี ก็ต้องลองใช้งานไปแล้วหลายโครงการ ซึ่งในที่สุดเราก็ต้องหวนกลับมาปรับปรุง code เหล่านั้นใหม่เมื่อพบว่าลักษณะการใช้งานเหล่านั้นขาดประสิทธิภาพสิ้นดี

โชคดีครับที่ พอหาเรื่องเหล่านี้ได้ใน internet มีผู้ใช้งานมากมายรวมถึงผู้ผลิตเองเขียนแนะนำการใช้งาน หรือแนวทางในการใช้งานเพื่อให้ได้ประสิทธิภาพสูงสุดหรือที่เรียกว่า Best practice ในการใช้งาน Library หรือ components นั้น ๆ ซึ่งในหัวข้อนี้ จะขอพูดถึงการใช้งาน ADO.NET

ในบทความนี้จะกล่าวถึงหลักปฏิบัติ หรือแนวทางในการปฏิบัติเพื่อใช้งาน ADO.NET ให้ได้อย่างมีประสิทธิภาพ คือ เพิ่มความเร็วและประหยัดเนื้อที่การใช้งานและลดภาระให้กับ network ซึ่งจะประกอบด้วยหัวข้อต่าง ๆ เหล่านี้

– .NET Framwork Data providers
– การใช้งาน DataReaders, DataSets, DataAdapters, and DataView
– การใช้ Commands
– การใช้ Connections
– การทำงานร่วมกับ XML

          ความเข้าใจใน ADO.NET technology อย่างถ่องแท้จะทำให้เราสามารถพัฒนาระบบได้เต็มประสิทธิภาพ และได้ศักยภาพสูงสุดของการทำงาน รวมถึง ความสามารถในการขยายระบบ และ function การทำงานที่ เป็นไปตามทิศทางของระบบที่ ควรเป็น ในบทความพูดถึงการปฏิบัติที่ดีในการใช้ objects ใน ADO.NET และ ให้คำแนะนำที่จะช่วยให้เราสามารถที่จะปรับปรุง การออกแบบ Application ที่ใช้ ADO.NET ให้ดียิ่งขึ้นและมีประสิทิภาพสูงสุด

.NET Framework Data Providers

Data provider เปรียบเสมือน สะพานเชื่อมระหว่าง application และ data source  ซึ่ง data provider ทำหน้าที่ในการส่ง ผลของ query จาก data source หลังจากที่ประมวลผล คำสั่งที่ data source แล้ว และ ส่งการเปลี่ยนแปลงใน DataSet กลับไปยัง Data source

เพื่อให้ได้ประสิทธิภาพสูงสุด ในการพัฒนา Application ควรเลือกใช้ .NET Framework data provider ให้เหมาะสมกับ Data source  data provider มีให้เลือกใช้อยู่หลายตัวครับ ตารางด้านล้างแสดงข้อมูล ของ data provider กับ data source ที่เหมาะสมกัน

Provider

Details

SQL Server .NET Data Provider Found in the System.Data.SqlClientnamespace.Recommended for middle-tier applications using Microsoft SQL Server version 7.0 or later.Recommended for single-tier applications using the Microsoft Data Engine (MSDE) or Microsoft SQL Server 7.0 or later. 
OLE DB .NET Data Provider Found in the System.Data.OleDbnamespace.Recommended for middle-tier applications using Microsoft SQL Server 6.5 or earlier, or any OLE DB provider that supports the OLE DB interfaces listed in OLE DB Interfaces Used by the OLE DB .NET Data Providerin the .NET Framework SDK. (OLE DB 2.5 interfaces are not required.)For Microsoft SQL Server 7.0 or later, the .NET Framework Data Provider for SQL Server is recommended.Recommended for single-tier applications using a Microsoft® Access database. Use of an Access database for a middle-tier application is not recommended.

Support for the OLE DB Provider for ODBC (MSDASQL) is disabled. For access to Open Database Connectivity (ODBC) data sources, an ODBC .NET Data Provider download is available and will be included in the .NET Framework SDK version 1.1.

ODBC .NET Data Provider The ODBC .NET Data Provider for is available for download.Found in the Microsoft.Data.Odbcnamespace.Provides access to data sources that are connected to using an ODBC driver.Note   The ODBC .NET Data Provider will be included in upcoming versions of the .NET Framework starting with version 1.1. The namespace for the included ODBC .NET Data Provider is System.Data.Odbc.
.NET Data Provider for Oracle The Microsoft .NET Data Provider for Oracle is available for download.Found in the System.Data.OracleClientnamespace.Provides access to Oracle data sources (version 8.1.7 and later).Note   The .NET Data Provider for Oracle will be included in upcoming versions of the .NET Framework starting with version 1.1.
Custom .NET Data Provider ADO.NET provides a minimal set of interfaces to enable you to implement your own .NET Framework data provider. For more information about creating a custom data provider, see Implementing a .NET Data Provider in the .NET Framework SDK.
SQLXML Managed Classes The release of XML for Microsoft SQL Server 2000 (SQLXML 3.0) contains SQLXML Managed Classes that enable you to access the XML functionality of Microsoft SQL Server 2000 and later, from the .NET Framework. For example, these classes enable you to execute XML templates, perform XML Path Language (XPath) queries over data at the server, or perform updates to data using Updategrams or Diffgrams.Building on the functionality from SQLXML 1.0 and 2.0, SQLXML 3.0 introduces Web Services to SQL Server 2000. With SQLXML 3.0, Stored Procedures and XML Templates can be exposed as a Web Service through SOAP.SQLXML 3.0 is available for download

อ้างอิงจาก http://msdn.microsoft.com/en-us/library/ms971481.aspx

การเชื่อมต่อกับ SQL Server ตั้งแต่ Version 7.0 ขึ้นไป

เพื่อให้ได้ประสิทธิภาพสูงสุด เมื่อต้องการเชื่อมต่อกับฐานข้อมูล Microsoft SQL server ควรเลือกใช้ SQL Server .NET Data provider.  SQL Server .NET Data provider นั้นออกแบบให้ เข้าถึง SQL Server โดยตรง โดยที่ไม่ต้องเกี่ยวข้องกับ technology อื่น ๆ  จากภาพด้าน แสดง  techonolgy ต่าง ๆ ที่ช่วยให้ เข้าถึง SQL Server

Figure 1. Connectivity methods for accessing SQL Server 7.0 or later

อ้างอิงจาก http://msdn.microsoft.com/en-us/library/ms971481.aspx

การเชื่อมต่อ ODBC Data Sources

ODBC .NET Data provider อยู่ใน namespace ที่ชื่อว่า Microsoft.Data.Odbc มีสถาปัตยกรรม แบบเดียวกับ  SQL Server .NET และ OLE DB Data provider. และใช้ connection strings มาตรฐานของ ODBC.

–>  ODBC.NET Data provider จะถูกรวมไว้ใน .NET Framework ตั้งแต่ version 1.1 เป็นต้นไป ซึ่งจะอยู่ใน namespace ชื่อ System.Data.Odbc

การใช้งาน DataReaders  DataSets DataAdapters และ DataViews

ADO.NET มี Object ที่ใช้ในการเข้าถึงข้อมูล และเก็บไว้ใน Memory คือ DataSet และ DataReader

–      DataSet เก็บข้อมูลในรูปแบบ relational ไว้ใน หน่วยความจำ  ประกอบด้วย ตาราง ข้อมูล ลำดับ และ ความสัมพันธ์ระหว่างตาราง

–      Data reader ให้ Streamของข้อมูล ในลักษณะไปข้างหน้าอย่างเดียว และอ่านได้อย่างเดียว

การ ใช้ DataSet มักใช้ควบคู่กับ DataAdapter เพื่อเชื่อมต่อไปยัง data source และมักต้องใช้ DataView เพื่อใช้ในการ sorting และ filtering ข้อมูลใน DataSet นอกจากนี้ DataSet ยังสามารถที่จะสร้าง strongly typed เพื่อให้สามารถเข้าถึงข้อมูลในตารางในลักษณะ property ของ object.

ในหัวข้อถัดไปจะกล่าวถึงการใช้งาน DataSet และ DataReader ทั้งเรื่องการใช้งานการ optimize การเข้าถึงข้อมูล รวมถึงเคร็ดลับการ optimize การใช้งาน DataAdapter และ DataView

คงต้องไว้คราวหน้าแล้วหล่ะครับ คราบขอไว้แค่นี้นะครับ ขอให้สนุกกับการเขียนโปรแกรม

s_teerapong2000@yahoo.com

Teerapong sontayaman

Categories: ADO.NET, DOT NET Tags:

Creating and Using a Static Library (C++) การสร้างและการใช้งาน static library ….

การสร้างและการใช้งาน static library ….

คงไม่ต้อง ให้คำอธิบาย นะครับ ว่า static library คืออะไร เพราะ ถ้าเราหาเรื่องนี้อ่าน ก็หมายถึงว่าเราอยากรู้ว่ามันเป็นอย่างไร ใช้งานอย่างไร  ครับ การใช้ static library นั้นเป็นหนทางที่ดีในการ reuse code หรือ การเขียนโปรแกรมแบบที่สามารถนำส่วนของ code ที่ใช้บ่อย ๆ  มารวมกันไว้ที่ใดที่หนึ่ง ให้สามารถถูกเรียกใช้ได้ ทั่วไป โดยไม่ต้อง ไปเขียน code ลักษณะเดียวกัน ทุกครั้งที่ต้องการใช้งาน  ไหนบอกว่าจะไม่อธิบายไง    นั่นก็คือ เขียนครั้งเดียว ใช้ได้ พร่ำเพรื่อ ฮะ ฮะ

ในบทความนี้ก็จะกล่าวถึง

  • การสร้าง static library
  • การเพิ่ม class ลงใน static library
  • การ สร้าง app ที่เรียกใช้ หรือ อ้างอิง function หรือ class ใน static library

ก่อนอื่นต้อง บอกก่อนว่า ผมอ้างอิง visual c++ ของ Microsoft นะครับ อาจจะเริ่มตั้งแต่  visual studio .NET ขึ้นไปนะครับ

การสร้าง static library

ในการสร้าง static library นั้นเรา ทำตาม ขั้นตอน เหล่านี้นะครับ

  • สร้าง  Project ใหม่       [เลือก New -> Project ]
  • กำหนด ให้ Project type เป็น Win32 [visual c++ ->  Win32 เลือก console application ]
  • กำหนดชื่อ project ให้เป็น MatchFuncLib หรือ ชื่ออื่นก็ได้ตามที่ต้องการ และกำหนด solution Name ให้เป็น  StaticLibrary  หลังจากนั้น ก็ click OK
  • click Next เมื่อ เจอหน้า Win32 Application Wizard
  • กำหนด Application type ให้เป็น static library
  • และเอา Precompiled header ออกpic2
  • สุดท้าย Click finish เพื่อจบขึ้นตอนการสร้าง Project

การเพิ่ม class ลงใน static library

  • สร้าง Header file ให้กับ class ใหม่
  • ที่ Project menu ,  เลือก Add New Item หลังจาก Add New Item dialog box แสดงขึ้นมาให้  เลือก code และ Header File(.h) กำหนดชื่อ ให้เป็น MathFuncsLib.h แล้ว กดปุ่ม Add  จะได้ file เปล่าๆ ขึ้นมาหนึ่ง file
  • เพิ่ม  code นี้ลงไป code นี้ผมเอามาจาก  http://msdn.microsoft.com/en-us/library/ms235627.aspx นะครับ หากต้องการ ข้อมูลเพิ่มเติม ให้เป็นตาม link ได้เลย

namespace MathFuncs
{
class MyMathFuncs
{
public:
// Returns a + b
static double Add(double a, double b);

// Returns a – b
static double Subtract(double a, double b);

// Returns a * b
static double Multiply(double a, double b);

// Returns a / b
// Throws DivideByZeroException if b is 0
static double Divide(double a, double b);
};
}

  • สร้าง source file โดย Project -> Add New Item เลือก C++ file(.cpp) กำหนดชื่อ ให้เป็น MathFuncLib.cpp และ click Add จะได้ file เปล่ามาอีกหนึ่ง file
  • พื่อ implement function ต่าง ที่อยู่ใน header file ขั้นแรกเรา จะทำการ include header file ชื่อ MathFuncLib.h และจึง implement ตัง functions ทั้งหมด ตาม code นี้

// MathFuncsLib.cpp
// compile with: /c /EHsc
// post-build command: lib MathFuncsLib.obj

#include "MathFuncsLib.h"

#include <stdexcept>

using namespace std;

namespace MathFuncs
{
double MyMathFuncs::Add(double a, double b)
{
return a + b;
}

double MyMathFuncs::Subtract(double a, double b)
{
return a – b;
}

double MyMathFuncs::Multiply(double a, double b)
{
return a * b;
}

double MyMathFuncs::Divide(double a, double b)
{
if (b == 0)
{
throw new invalid_argument("b cannot be zero!");
}

return a / b;
}
}

เอาละครับ มาถึงตรงนี้เรา ก็ ได้ทำการ สร้าง Static library Project ขึ้นมาแล้ว ซึ่ง ถ้าเราสังเกตจะเห็น ว่ามันมี สอง file ชื่อ MathFuncsLib.h และ MathFuncsLib.cpp เราประกาศ class ไว้ใน MatchFuncsLib.h และ implement ใน MatchFuncsLib.cpp นะครับ หลังจากนี้ เราจะทำการ build project ให้เป็น library
ก่อนทำการ Build ให้ทำการ กำหนด project properties ให้ กำหนด configuration properties เป็น general และ Configuration Type ให้เป็น static library(.lib) กดปุ่ม OK เพื่อบันทึกการเปลี่ยนแปลง
Compile static library โดยการ Build Solution จาก Build menu เป็นการจบขั้นตอนการสร้าง static library เพื่อให้โปรแกรม อื่นเรียกใช้งาน

ต่อไปเป็นตัวอย่าง การเรียก ใช้  function จาก static library จาก console application

–          สร้าง console application ( win32 console application )  โดยอาจ ตั้งชื่อให้เป็น  MyExecRefsLib.cpp

–          เพื่อที่จะใช้ math routines ที่สร้างไว้ใน  static library เราจะต้องทำการ อ้างอิงไปหา หรือ Reference

  • ให้เลือก  Reference จาก Project menu ใน properties page dialog box ให้ขยาย common properties node และเลือก reference  แล้วเลือก Add New Reference
  • ขณะนี้ Add reference dialog box จะแสดง   ใน dialog box นี้แสดง รายการ  libraries ทั้งหมด ที่เราสามารถอ้างอิง  ในส่วนของ Project tab นั้นแสดง Projects ทั้งหมด ที่อยู่ใน solution และ libraries ต่าง ๆ ที่มีอยู่  ใน Project tab นี้เรา เลือก MathFuncsLib แล้ว OK
  • เพื่อให้เราสามารถ อ้างอิงไปยัง header files ของ static library ได้ เราต้อง แก้ไข include directories path  โดย ทำดังนี้ ใน Property Pages dialog box, ขยาย Configuration node ขยาย C/C++ node เลือก General
    • เพิ่ม  Additional Include Directories  พิมพ์ หรือ เลือก path ที่  MathFncsLib.h ตั้งอยู่

#include "stdafx.h"
#include <iostream>
#include "MathFuncsLib.h"

using namespace std;
//#include "iostream.h"

int _tmain(int argc, _TCHAR* argv[])
{
double a = 7.4;
int b = 99;

cout << "a + b = " <<
MathFuncs::MyMathFuncs::Add(a, b) << endl;
cout << "a – b = " <<
MathFuncs::MyMathFuncs::Subtract(a, b) << endl;
cout << "a * b = " <<
MathFuncs::MyMathFuncs::Multiply(a, b) << endl;
cout << "a / b = " <<
MathFuncs::MyMathFuncs::Divide(a, b) << endl;

return 0;
}

ทั้งหมด คงพอจะเห็น การทำงานนะครับ หวังว่าจะได้ อะไร ไปบ้าง นะครับ มีอะไร ไม่เข้าใจ mail มาคุยกันนะครับ s_teerapong2000@yahoo.com

Categories: C++, DOT NET, OOP

View State , ASP.NET State Management

HTTP นั้นเป็น protocol ประเภทที่เรียกว่า stateless  ขึ้น มาแบบนี้ programmer ที่ทำงานด้านนี้ทราบดีอยู่แล้ว แต่สำหรับมือใหม่ หรือเพิ่งเข้ามาจับงานประเภท web base programming ละก็จะต้องทำความเข้าใจกันซะก่อนเป็นเบื่องต้น และเข้าใจมาก ๆ ในเบื้องกลาง และเข้าใจสุด ๆ ในเบื้องปลาย ฮะ ฮะ
Stateless เป็นอย่างไรนะหรือครับลักษณะก็คือ ทุกครั้งที่มีการ request ไปยัง server ( หมายถึง webbrowser นะครับ ) เสร็จแล้วก็จะ disconnect เลยนะครับไม่มีการ คง connection ไว้ เพราะฉะนั้น จะไม่มีการคงอะไรไว้หรือรักษาอะไรไว้เลยระหว่าง สอง connection แบบนี้แหละครับที่เรียกว่า stateless เหตุผลของ architecture นี้ก็คือ เพื่อให้ server สามารถรองรับการ request พร้อม ๆ กัน หลาย ๆ พัน หลาย ๆ หมื่น client โดยที่ไม่เกิด run out of memory นะครับ แต่ปัญหา ของมันก็คือ อืม เราไม่เรียกว่าปัญหา เรียกว่าข้อด้อยของมันดีกว่า ข้อด้อยของมันก็คือ programmer จะต้องหา techniques อื่นเพื่อรักษาข้อมูลระหว่างที่มีการ request และสามารถดึงข้อมูลเหล่านั้นมาใช้งานได้ตามต้องการนั่นเอง

ที่เกรินมาทั้งหมดนี้ก็ เพราะว่า ผมจะหาข้อมูลและเขียนเกี่ยวกับ State Management ในหลาย ๆ ระดับ มาเล่าสู่กันฟัง และก็จะรวมถึง technique การส่งผ่านส่งผ่านข้อมูลจาก page หนึ่งไปยังอีก page ด้วย ดังนั้นในหัวข้อเหล่านี้มันก็คง จะมีหลาย ๆ ตอนอยู่นะครับ ถ้าพลังมีมาก ผมคง ให้รายละเอียดได้ทั้งหมด

View State

View state เห็นจะเป็นหัวข้อแรกที่ผมเลือก ที่จะพูดถึงเพราะ View state นี้เราใช้ในการรักษาข้อมูล ภายใต้กรอบการทำงาน page เดียวเท่านั้น ( ASP.NET web controls ใช้ View State เป็นพื้นฐานอยู่แล้ว ) ซึ่ง View state มันจะทำให้เรารักษาข้อมูลระหว่าง postbacks ได้ ( เหตุการณ์ที่จะทำให้เกิด postback เช่น การ click ปุ่มเป็นต้น )
Page object มี property ที่ชื่อว่า ViewState เป็นตัวช่วยให้เราสามารถที่จะเพิ่มข้อมูลเข้าไปใน View State Collection ได้ และ ข้อมูลที่เราสามารถที่จะเก็บลงใน view state ก็เป็นได้ทั้ง simple data types และ ก็ objects ที่เราสร้างขึ้นมา
ต่อไปเรามาดูการใช้งาน View State กันนะครับ เนื่อง จาก View State นั้นมีรูแบบ ที่เรียกว่า dictionary collection ก็หมายถึงว่าข้อมูลแต่ละตัวจะถูกอ้างอิงด้วย string name ที่แตกต่างกัน เช่น

ViewState[“Counter”] = 1;

นั่นเป็นการ เก็บ 1 ลงใน ViewState Collection และอ้าอิงด้วยชื่อที่มีความหมาย คือ Counter ตรงนี้สำคัญนะครับ ถ้า Counter ยังไม่เคยปรากฏอยู่ใน ViewState collection เลย มันก็จะเพิ่ม Counter เข้าไปและเก็บค่า 1 แต่ถ้า Counter มีอยู่แล้ว มันจะแทนที่ค่าเดิมด้วย 1 นะครับ

การ retrieve ข้อมูล เราก็อ้าอิง ด้วยชื่อ Counter ในลักษณะเดียวกับการ บันทึกข้อมูลงไป ( Counter เราเรียกว่าเป็น Key name ) และเราก็ต้องทำ casting ด้วย data type ที่เหมาะสมนะครับ เพราะการเก็บค่าเข้าเป็นใน View state collection นั้นมักจะถูก ทำให้เป็น object โดยอัตโนมัติ ( กรณีที่พวก simple data type เช่น integer ) ดังนั้นต้อง casting ก่อนเพื่อให้ได้ข้อมูลที่ถูกต้องและนำไปใช้งาน ต่อไปเป็นตัวอย่างของ code แสดงการ retrieve ข้อมูลจาก View State collection

int counter ;
if (ViewState[“Counter”] != null)
{
Counter (int)ViewState[“Counter”];
}

ถ้าเรา พยายามที่จะ retrieve ข้อมูลซึ่งไม่มีเก็บอยู่ใน หรือ ไม่ปรากฏอยู่ ใน Collection เราจะได้ NullReferenceException มาแทน ใน code ก็เลยต้องทำการ ตรวจสอบซะก่อนว่า มีข้อมูลปรากฏอยู่หรือไม่ ถือว่าเป็นหลักปฏิบัติโดยทั่วไป นะครับ
จากตัวอย่างที่ผ่านมา เราสามารถประยุกค์ใช้กับ Data types ชนิดอื่นได้ (Simple data types) นอกจากนี้เรายังสามารถที่จะบันทึก ข้อมูลที่เป็น object ลงใน Veiw State ได้ด้วยเช่นกัน แต่การบันทึกข้อมูล objects ลง View State นั้น Object จะต้องเป็น Object ที่ประกาศให้สามารถ แปลงให้เป็น bytes  stream ได้ หรือ ที่เรียกว่า serialization ครับ การทำก็ไม่ได้เป็นเรื่องยากอะไรครับ แค่เพิ่ม ‘Serializable’ attribute ไว้ที่ การประกาศ class  ดังตัวอย่าง

[Serializable]
public class Student
{
public string firstName;
public string lastName;

public Student(string fName, string lName)
{
firstName = fName;
lastName = lName;
}
}

การเก็บค่าลงใน View State

// Storing a student in view state.
Student stud = new Student(“John”, “Doe”);
ViewState[“CurrentStudent”] = stud;

และการดึงข้อมูลออกมาใช้งาน

// Retrieve a student from view state.
Student stud = (Student) ViewState[“CurrentCustomer”];

อย่าลืมนะครับ เวลาเราดึงข้อมูลจาก View Sate จะต้องทำการ casting ให้เป็น Datatype เดียวกับที่เรา ใส่ลงไปนะครับ ในเรื่อง serializable นั้น มีข้อกำหนดดังนี้นะครับ

  • class จะต้องกำกับด้วย serializable attribute
  • derive ก็จะต้อง เป็น serializable ด้วย
  • ตัวแปร private ของ class ก็จะต้องเป็น serializable หรือ ถ้ามี none serializable ก็จะต้องกำกับ ด้วย [none serializable] attribute

ตัวอย่างการใช้งาน สมมติว่าเราจะทำ PostBack counter ก็คือเราจะทำการเพิ่มค่าทีละ 1 ทุกครั้งที่มีการ click ปุ่มนะครับ ลองมาดูกันว่าเป็นอย่างไร

อันดับแรกเรา สร้าง page ใส่ control ดังต่อไปนี้

และที่ code เป็นอย่างนี้ครับ อันดับแรกเป็นของ Page load event

protected void Page_Load(object sender, System.EventArgs e)
{
//First we check if the page is loaded for the first time,
if (!IsPostBack)
{
ViewState[“PostBackCounter”] = 0;
}
//Now, we assign the variable value in the text box
int counter = (int)ViewState[“PostBackCounter”];
Label1.Text = counter.ToString();
}

ถัดมาเป็น ของ OnClick ของ Button1

protected void Button1_Click(object sender, System.EventArgs e)
{
int oldCount = (int)ViewState[“PostBackCounter”];
int newCount = oldCount + 1;
//First, we assign this new value to the label
Label1.Text = newCount.ToString();
//Secondly, we replace the old value of the view state so that the new value is read the next //time
ViewState[“PostBackCounter”] = newCount;
}

ครับ จาก code จะเห็นว่า ทุกครั้งที่มีการ Click ปุ่ม จะทำการเพิ่มค่าให้ PostBackCounter ทีละหนึ่งนะครับ แต่ครั้งแรกที่ load page นี้จะทำการ set ค่าไปที่ 0
ครับที่กล่าวมาและตัวอย่าง ต่าง ก็คงพอที่จะได้ แนวความคิดการใช้งาน View state บ้าง ไม่มากก็น้อยนะครับ

การทำ Deploy .NET Window application

December 22, 2008 7 comments

พอดีจะทำ Setup project  กับ โปรเจคเล็ก ๆ ทีทำไว้ ต้องการให้รวมเอา Ms Access ไปด้วยและต้อง รวมเอา Crystal Report Runtime เข้าไปด้วย ยังหาข้อมูลตรงนี้ไม่ได้ ก็เลยตั้งใจว่าคงต้อง ให้เวลากับมันสัีกนิด เพื่อทำความเข้าใจจริงจัง แล้วไหน ๆ ทำแล้วก็ เผยแพร่เพื่อ เพื่อน ๆ โปรแกรมเมอร์ และนักพัฒนาโปรแกรม ด้วยกัน …

ไหน ๆ ก็ พูดแล้วกล่าวถึงคำว่า Deployment กันสักนิด  หลังจากที่เราได้พัฒนา Application เส็จสิ้นสมบูรณ์แล้ว ถึงเวลาที่เราจะนำโปรแกรมไปให้กับผู้ใช้งาน หรือสร้างเป็นชุด Installation เพื่อทำให้โปรแกรมของเราสามารถที่ทำงานบนเครื่องผู้ใช้ได้อย่างสมบูรณ์ เราก็ต้องสร้าง ชุด Install ที่สามารถนำไฟล์ทุกไฟล์ที่เกี่ยวข้อง กับการทำงานของโปรแกรม ไม่ว่าจะเป็น .exe , .dll , component ต่าง ๆ ที่เกี่ยวข้อง  third party component  ไฟล์อื่น ๆ เป็นต้น หรือแม้แต่การสร้าง directory การสร้าง shortcut  การทำ environment บนเครื่องเป้าหมาย ให้มีสภาวะเช่นเดียวกับ เครื่องที่เราใช้พัฒนา  กระบวนการที่เราทำสิ่งเหล่านี้ก็คือการ Deployment นั่นเอง

วิธีการที่เราจะกล่าวถึง สำหรับการ Deploying .NET Application คือการใช้ Visual studio .NET Deployment Tools  ซึ่งใช้เครื่องมือที่มีมาพร้อมกับ .NET Visual studio ในบทความนี้ เราอ้างอิง Visual Studio 2005 นะครับ ซึ่งเจ้าเครื่องมือนี้ เราสามารถใช้สำหรับการทำงานดังต่อไปนี้นะครับ

  1. ใช้ Copy ไฟล์ที่จำเป็นทั้งหมดไปยังเครื่อง เป้าหมาย
  2. นอกจากที่มันทำในข้อ 1 แล้วมันก็ยังสามารถเอาไฟล์เหล่านั้นไปไว้ยัง Folders ต่าง ๆ ตามความต้องการของโปรแกรม
  3. และเรายังสามารถใช้ให้มันสร้าง Registry entry ได้ตามต้องการอีกด้วย
  4. และยิ่งไปกว่านั้นเราสามรถทำ custom Dialog ได้ และตรวจสอบ ความต้องการเบื่องต้น เช่น ตรวจสอบว่ามี .NET Framework บนเครื่องเป้าหมายหรือไม่ เป็นต้น
  5. และอื่น ๆ อีก เราสามารถเลือกใช้ได้ตามความต้องการของเรานะครับ

เรามาดูกันที่ เมื่อเริ่มต้นสร้างเราสร้างกัน อย่างไร การเริ่มต้นสร้าง นั้นใช้วิธีการเดียวกับการสร้างโปรเจค นะครับ กล่าวคือเมื่อเราเริ่มสร้างโปรเจค เราเลือก Project type ที่ชื่อว่า Setup Deployment  project  เราสามารถเลือก  template สำหรับการ deployment ได้ตามชนิดของ Application ที่เราทำนะครับ ซึ่งมันก็จะมี

  1. Setup Project สำหรับการสร้าง Deployment ให้กับ Project ธรรมดาที่ทำงานโดยใช้ windows form
  2. Web Setup Project สำหรับสร้าง Deployment ให้กับ Project ที่เป็น Web application
  3. Merge module project สำหรับ การสร้าง Deployment ให้กับ component หมายถึงเราจะ deploy component ที่เราสร้างนะครับไม่ใช่ application
  4. Cab project ก็เช่นเดียวกัน นะครับสำหรับการ deploying component   เช่น component ที่สร้างสำหรับการทำงานบนเครื่อง client เราใช้ component ชนิดนี้วางไว้บน Web server เมื่อ Web browser ต้องการ component การสามารถ download จาก server และทำที่เครื่อง client ได้ คงจะพอนึก app. ประเภทนี้ออกนะครับ
  5. Web Wizard Project มี Wizard  นำทางตลอดทุกขั้นตอนในการทำงาน เหมาะสำหรับ มือใหม่นะครับ จะเริ่มที่นี่
  6. Smart Device Cab Project สำหรับการ Deploying Application ที่ทำงานกับ Pocket PC หรือ smart Phone

เอาหล่ะครับเข้าประเด็นดีกว่า ความต้องการก็คือ เรา ต้องการ ให้มีการสร้าง path ที่เครื่องปลายทางและ นำเอา file Database ของเรา รวมไปใส่ไว้ที่ path นั้น รวม  Crystal report และ .Net framework ด้วย . นั่นคือทั้งหมด ที่ต้องการ

เราเริ่มด้วยการสร้าง Set up Project  เราสามารถที่จะสร้างไว้ภายใน Solution เดียวกันก็ได้ หรือ สร้างไว้ต่าง Solution กันก็ได้ (แล้ว add project เข้ามาทีหลัง) ผมขอกล่าวกึงวิธีการ สร้าง ไว้ภายใน Solution เดียวกันก็แล้วกันนะครับ เพราะเวลาเราทำ Installation file ก็มักจะทำ ให้กับ solution ใด solution หนึ่งเท่านั้น

  • หลังจากเรา เปิด  Solution ขี้นมาแล้ว คือเมื่อเรา เปิดโปรเจคใดโปรเจคหนึ่ง มันก็จะเปิด Solution ที่โปรแจคนั้นอยู่ขึ้นมาทั้งหมด เราก็ Add โปรเจคใหม่เข้าไป โดยเราเลือก ให้เป็น  “Setup Project” นะครับ แล้วตั้งชื่อให้กับโปรเจกสักหน่อยก็ได้ ไม่งั้นเราก็จะได้ชื่อ Default ซึ่ง เป็น Setup1 Setup2 .. หรืออะไรก็ตาม pic11

pic2

  • ถัดมาเราจะได้ view ที่เรียกว่า File system view  ซึ่งจะมีรายการของ File system ดังนี้
    • Application Folder ซึ่งมันก็คือ  “C:/Program Files/ชื่อเรา[manufacturer]/projectductname”
    • Profile Folder มันคือ  “C:/Program Files” ของเรานั้นเอง
    • User’s Desktop คือ path ที่อ้างไปยัง หน้าจอ desktop ของ  User แต่ละคนนั่นเอง
    • สุดท้าย ก็คือ User’s Program Menu คือ path ที่อ้างไปยัง All programs ใน start นั่นเอง

ที่จริงเราสามารถเพิ่มเข้ามาได้อีก กรณีที่เรามีความต้องการใช้งานมากกว่านี้  คลิกขวาที่ File system on target machine แล้วเลือก Add special folder ผมจะไม่กล่าวถึงในตอนนี้ นะครับเพราะเท่าที่มีนั้นเพียงพอต่อความต้องการของผมแล้ว (ฝรั่งเขาเรียกว่า commonly used ไง ยังไงก็ต้องใช้มัน )

  • ขั้นตอนต่อไปคือ การทำ Project output ก็คือว่าจะให้ Project ไหนเป็นตัวโปรแกรมหลักในการ Deploy ครั้งนี้ หรือ main project นั้นแหละครับ เราผมจะให้มันสร้างภายใต้ Application Folder นะครับ ก็คลิกขวาที่ Application Folder แล้วเลือก Add –> Project output นะครับ แล้วจะมีโปรเจค ให้เราเลือก เราก็เลือกว่า โปรเจคใดที่เราต้องการ ดังรูป

pic3 เรา Project ใน combobox แล้ว Primary output ที่ Listbox ด้านล่าง นะครับ แล้วก็ OK

  • เราจะได้ Primary output ขึ้นทางด้านขวามมือนะครับ หากเราสร้าง class library  project ที่เราอ้างอิงจาก primary เราก็จะเห็น .dll ของ class library เหล่านั้นแสดงอยู่ด้วย ดังนี้
  • pic4จะเห็นว่า ภายใต้ Application Folder ของผมมี Sub folder เพิ่อมเขามาอีก นั้นคือเราเพิ่มเขามา เพื่อให้เป็น sub folder ที่อยู่ภายใต้ folder เดียวกับ .exe file นั่นเอง คือผมต้องการให้มี folder สำหรับ database (ใส่ ฐานข้อมูล MsAccess) และ reports ที่เราเรียกใช้ระหว่างโปรแกรมทำงานนั่นเอง การเพิ่มก็เพียงแค่ คลิดขวาที่ Application folder แล้วเลือก Add->Folder เท่านั่นเอง ครับ
  • ส่วนไฟล์ที่ต้องการ add เข้าไปในแต่ละ Folder (database และ reports )นั้นก็ คลิกวาที่ Folder นั้นแล้วเลือก Add->file แล้วเราก็ไปเลือกไฟล์ที่เราต้องการ เช่น filename.mdb เป็นต้น มันก็จะทำการรวม file นั้นเขามาในโปรเจค เช่นเดียวกันกับ reports ซึ่งผมใช้ crystal report ในระหว่างการเขียนโปรแกรมมมันก็จะรวมอยู่กับ code file  ผมก็ add มันเขามาใน folder reports ครับ แต่ข้อที่ควรรระวังก็คือ คุณตั้งกลับไปจัดการกับ การอ้างอิง file เหล่านี้อีกครั้ง ให้ตรงกับ ที่ทำไว้ใน setup project และ build ใหม่อีกครั้ง ผมหมายถึงใน primary project นะครับ
  • ต่อไปเราจะทำการสร้าง shortcut ที่หน้า desktop และสร้าง item ใน Programe Menu    จริงแล้วไม่ใช่เรืองยากเลย ครับ อันดับแรกเราสร้าง short cut ก่อน โดยการคลิกขวาที่ primary output from ……… (active) แล้วก็เลือก “Create shortcut to primary…… ” หลังจากนั้นเราก็จะได้ shortcut มาในชื่อเดียวกันเราก็เปลี่ยนชื่อซะให้เหมาะสม แล้วก็ ดึงไปวางไว้ – หากต้องการให้เป็น shortcut ที่หน้าจอ desktop ก็ วางไว้ที่ User’s Desktop folder ด้านซ้ายมือ
  • ในกรณี User’s Program Menu นั้น หากเรามีหลาย Shortcut เราอาจต้องการทำให้เป็นกลุ่มไม่ปะปนกับ menu อื่น ๆ เราก็ต้อง สร้าง folder ภายใต้ User’s Program Menu ด้วย ใช้ชื่ออะไร ก็ตาม หลังจากนั้นเราก็ สร้าง short cut เช่นเดียวกันกับ ที่กล่าวมาก่อนหน้านี้ แล้วก็ลากมาวางไว้ที่ folder ที่อยู่ภายใต้ User’s Program Menu นี้ เราก็จะได้ menu ตามที่เราต้องการ
  • นั่นเป็นทั้งหมด ที่ผมทำนะครับ อ้อมีเพิ่มเติมนะครับ เรื่อง Prerequisites … ในกรณีของผมนี่ ต้องการให้ Setup ของผม ตรวจสอบและ install  crystal report สำหรับ .net framwork 2.0 ด้วย และ ก็รวมถึง framework ด้วยนะครับ เราก็สามารถที่จะกำหนดได้ดังนี้นะครับ  ใน solution explorer ให้คลิกขวาที่ setup project แล้วเลือก properties นะครับจะได้หน้าจอ properties ขึ้นมาเราก็เลือกไปที่ปุ่ม prerequisites นะครับแล้วเราก็เลือก จะเอาอะไรก็ ตามต้องการ pic5
  • จากรูปนะครับ เลือกเสร็จด้านล่าง ถัดมาเราก็เลือก Download prerequisties from the same location as my application นะครับ ผมไม่แน่ใจว่า option นี้หมายถึงให้เอาจาก Installation ที่เราทำใช่หรือป่าวนะครับ เพราะผมยังได้ลอง install เครื่องอื่น เลยไม่ clear ตรงนี้ แต่ผมสังเกตุเห็นว่า ภายใต้ Debug จะมี sub folder ของ library เหล่านี้ปรากฎอยู่ อาจจะเป็นแค่ bosttrap โปรแกรมก็ได้ นะครับ คือมันเริ่มต้น และ download ส่วนที่เหลือ จาก internet นะครับ
  • ในกรณี prerequisites นี้หลายท่านแนะนำว่า ให้เรา แยกต่างหากไปเลย หมายถึง ถ้าเราต้องการ ให้ผู้ใช้ลง .net framework เราให้ ผู้ใช้ install .net framework ก่อน หรือเราจัดให้พร้อมกับชุด install ก็ได้ เช่นเดียวกันกับ crystal report นะครับ หลายท่านก็บอกให้แยก ประโยชน์ก็คือ มันจะ update ตัวมันเองได้ หากมีการ update เพิ่มเติม เขาว่ามาแบบนั้นนะครับ
  • ครับ เพิ่มเติมข้อที่แล้วอีกนิดนะครับ สำหรับใครต้องการ  crystal report  (runtime) ก็มา ได้ที่นี่นะครับ https://www.sdn.sap.com/irj/boc/businessobjects-downloads แล้วก็ คลิกที่ Get Crystal Reports, Crystal Reports Server, and Xcelsius downloads
  • ส่วน .NET Framework คงไม่ต้องบอกนะครับว่า ไป download ได้ที่ไหน
  • มาถึงสุดท้าย ท่านก็ build setup Project แล้วก็ลอง install ดูนะครับ  แล้วก็ลอง run ดูนะครับ  เรื่องการตรวจสอบ เรื่อง .net framework หรือ crystal report นั้นควรจะต้องไปหาเครื่องอื่นลงนะครับ เครื่องที่ยังบริสุทธิอยู่นะครับ ถึงจะรู้ว่า ผิดถูกประการใด ส่วนเรื่อง path ต่าง ๆ นั้นเราตรวจสอบ ได้บนเครื่องเรา แต่ต้องระวังนะครับ บางที่ เราอาจไม่เห็นขอผิดพลาดเพราะว่า บางครั้งถึงแม้เราแก้ไข path อ้างอิง ไม่หมด แล้ว ปรากฏว่าโปรแกรมทำงานได้ ที่ได้ก็เพราะว่า path เดิมของไฟล์ที่เราอ้างอิงนั้นมันยังมีอยู่ มันก็เลยยังทำงานได้ พอไปลงจริงอาจจะเกิดปัญหาได้ ต้องอรบคอบหน่อยนะครับตรงน้
  • ก็คงจะจบลงตรงนี้ก่อนะครับ คิดว่าคงพอเป็นแนวทางให้กับหลาย ๆ ท่านได้ นำเอาไปต่อยอดกันเอาเอง นะครับ หากมีอะไรเพิ่มเติมหรือ ท้วงติงก็ comment มา่ได้นะครับ หรือ จะเพิ่มเติมมาก็ได้เพื่อเป็นประโยชน์กับเพื่อน ๆ คนอื่น ต่อไป นะครับ หรือจะ mail มาคุยกันก็ได้นะครับ s_teerapong2000@yahoo.com

Common Language Infrastructure ( CLI ) ภาคเกริ่นนำ

October 14, 2008 2 comments

อืม เห็นขึ้นต้นอย่างนี้ ไม่มีอะไรแปลกหรอก ครับ พอดีมีเรื่องอยาก เขียน คือเรื่องของ Mono-project หลายคนเห็นชื่อนี้คงนึกออก หลายห่านไม่รู้จักหลายท่านบอกว่าคุ้น ๆ หู  แต่ก่อนที่จะไปเรื่อง Mono-project ผมก็คงจะต้องกล่าวถึง Common Language Infrastructure กันเสียก่อน เป็นข้อมูลพื้นฐานและเข้าใจว่า Mono-project เป็นมาอย่างไร นะครับ 🙂

ก็อย่างที่ได้เกรินนำไปนั้นแหละครับ เรามาพูดกันถึงเรื่อง Common Language Infrastructure หรือ CLI กันว่ามันเป็นอย่าไร ทำไมต้องรู้จักมัน และมันเกี่ยวกับ .NET อย่างไร

CLI เป็นข้อกำหนดหรือ specification ที่ทาง Microsoft เขาได้พัฒาขึ้นมา ซึ่งก็เป็น ตัว .NET Technology ของเขาเองนั้นแหละครับ (ปัจจุบันเป็นมาตรฐาน ECMA-335) ที่จะทำให้ application ที่ถูกพัฒนาจาก high level programming language ต่าง ๆ สามารถทำงานได้ บนระบบที่มี environment ต่าง กันได้ หรือ กล่าว ง่าย ๆ ก็คือสามารถทำงานบน platform ต่าง ๆ กันได้โดยเป็น ลักษณะ Platform independent นั่นเองครับ

อันที่จริง  Java เขานำไปแล้วครับ แต่ว่า .NET กำลังมาตอนนี้ แต่ที่แรงกว่า Java คือ มันสามารถเขียนได้ด้วยภาษาต่าง ๆ ได้ ที่ compatible หรือ ภาษาที่ทำตาม specification ที่ CLI กำหนด หรือ เอาตามมาตรฐาน EMCA-335 นั่นเอง ซึ่งมันมีเยอะ นะครับ นอกจาก ของ Microsoft เองแล้วยังมีภาษาอื่น อีกหลายภาษา ผมเอง ก็จำไม่ได้ว่ามี ภาษาอะไรบ้างที่พอจำได้ก็อย่างเช่น COBOL เป็นต้น
CLI specification หรือ ข้อกำหนด CLI  มีหลัก ๆ อยู่ 4 เรื่อง [Wikipedia – Common languague Infrastructure]

คือ

  • Common Type System (CTS) เกี่ยวกับ type และ operations ที่ CTS-compliant(ภาษาต่าง ๆ) ใช้ร่วมกัน  CTS ถือว่าเป็นหัวใจสำคัญ ของ CLI เลยหล่ะครับ
  • Metadata ก็คือข้อมูลต่างๆ ของโปรแกรม ซึ่ง CLI ใช้ในการอธิบายและอ้างอิง types ต่าง ๆที่ กำหนดใน CTS  และ มันก็จะถูกผนวกเขาใน assemblies ในระหว่างที่ทำการ compilation
  • Common Language Specification (CLS) เป็นกฏพื้นฐาน ภาษาต่าง ๆ จะต้องทำตาม เพื่อที่ภาษาเหล่านี้จะสามารถทำงาน ด้วยกันได้ (ภาษาที่ว่านี้ ก็คือภาษาที่ทำตาม specification ของ CLI นะครับ หรืออาจจะเรียกว่า CLI language ก็ได้เนอะ ) เพราะฉะนั้น module ที่เขียนจากภาษาหนึ่ง ก็สามารถถูกอ้างอิงหรือ เรียกใช้จากอีกภาษาหนึ่งได้ ว่างั้น
  • Virtual Execution System (VES) เมื่อ ภาษาเหล่านั้น compile และได้ managed code ออกมา VES จะเป็นตัว execute ซึ่งก็ใช้ข้อมูลต่าง ๆ ที่ฝังมาด้วย ( meta data )


ภาษาต่าง ๆ ( CLI language ) หลังจาก compile code ของตัวเอง แล้วจะได้  intermediate language หรือ Common Intermediate Language ( CIL ) หรือ managed code นั้นและเนอะ ซึ่งมันยังไม่หยั่งลงไปถึง platform hardware คือมันยังมองผ่าน abstract อยู่นะครับ  ถัดมา  VES จะเป็นตัว compile CIL ต่อโดย ทำงานร่วมกับJIT  แปลง code เหล่านั้นให้สามารถทำงาน ได้ กับ hardware ที่มันทำงานอยู่ นะสิ ก้คือ ได้ machine language ที่ทำงานกับ hardware นั้น ๆ อืมก็ประมาณนี้แหละ อ่าว แล้วไงหล่ะครับพูดไปพูดมา Common Language Runtime ( CLR ) หายไปไหน หว่า อันที่จริงไม่ได้หายไปไหนหรอก เพราะมันก็คือ environment ที่ VES และ JIT ทำงาน อยู่ นั้นแหละ ครับ 🙂

คราวนี้ตามมาอีกสักนิดนะครับ หลังจากนี้มันก็จะก้าวไปสู่ Cross Platform นะสิครับ  ตราบใดก็ตามที่เรา ว่าไปตาม CLI specification ความสำเร็จที่ code ของเราจะทำงาน ได้ โดยไม่ยึดติด platform ก็มาถึง ปัจจุบัน นอกจาก นอกจาก Microsoft  ที่ดำเนินตาม CLI (Microsoft .NET) แล้ว  ก็มีอีกหลาย ๆ third party ที่พยายามจะ implement  CLI เจ้าหนึ่งที่กำลังมาแรง ผมคิดเองนะ ก็คือ Novell’s Open-source Mono Project นี่แหละครับคือประเด็นที่กล่าวมาทั้งหมด
ตอนนี้ Mono project ได้ทำการ implement CLI ให้กับหลาย plate form คือ Apple’s OS X  Linux และ ก็ Sun Solaris และอื่น ๆ อีก รวมถึง Microsoft Window ด้วย ทำแข่ง Micro Soft ซะ งั้นไม่รู้ว่าคิดอะไรอยู่ เอาว่าผมจะพูดถึงเรื่อง Mono project ในตอนต่อไป ก็แล้วกันนะครับ  ค่อยติดตามก็แล้วกัน

Delegates and Events ตอนที่ 3

October 12, 2008 2 comments

สวัสดีครับ คิดว่าคงมี สักคนที่ได้มีโอกาสอ่าน blog ผม ก็เลยสวัสดีไปงั้นแหละ สำหรับตอนนี้เป็น การพูดถึง delegates ต่อจากตอนที่แล้ว ครับ ซึ่งเราคงจะได้เข้าใจการใช้งาน delegates ไม่มากก็น้อย สำหรับในตอนนี้ จะพูดถึงเรื่อง Multicast delegates ครับ  delegates สามารถที่จะอ้างอิง function หรือ method ได้มาก กว่าหนึ่งนะครับนี่ นั่นก็คือ delegates object หนึ่งตัวสามารถที่จะอ้างอิง ไปยัง หลาย ๆ  method และเมื่อเรียก delegates นั้นก็ทำให้ method ที่มันอ้างอิงอยู่ ทำงานในคราวเดียวกัน ครับ

ครับจากที่ได้กล่าวมา ข้างต้น  delegates นั้นที่จริงแล้วเป็น multicast ก็หมายถึงโดยปกติแล้วมันสามารถที่จะชี้ไปยัง function หรือ method ได้หลาย method หรือ function ในคราวเดียวกัน  Base case ของ multicast delegates ก็คือ System.MulticastDelegate ครับ   ดังนั้น การเรียก delegates object ครั้งเดียวก็สามารถที่จะสั่งให้ หลาย method ทำงานได้ แต่ต้องไม่ลืมนะครับว่า Method เหล่านั้นต้องเป็นไปตามข้อกำหนดของ delegates นะครับ นี้สำคัญ นะครับ 🙂

Delegates and Events ตอนที่ 2

ไม่รู้ว่าจะเรียกตอนที่ 2 ได้หรือป่าว แต่ก็เป็นตอนที่ต่อจาก ตอนที่แล้ว ยังคงเป็นตัวอย่างเพิ่มเติมอีกเพื่อให้มีความเข้าใจมาก มาก และ มากขึ้นอีก เนื่องจาก Concept  ของ delegates นั้นเป็นเรื่องที่สำคัญมาก สำหรับการเขียนโปรแกรมในขั้น Advance ต่อไป จริง ๆ จะบอกให้ อยากให้เพื่อน ๆ หรือน้อง ๆ โปรแกรมเมอร์ ได้เข้าใจ จริง ๆ

เอาละครับเรามาเข้าเรื่องของเราเลยดีกว่า เราจะดูตัวอย่างของ delegates อีก 2 ตัวอย่าง โดยจะพิจารณาการทำงาน ทีละขั้น นะครับ พิจารณา code ต่อไปนี้ เป็นตัวอย่างต่อไป

namespace ConsoleApplication1
{
    public class MyClass
    {
        public delegate void LogHandler(string message);

        public void Process(LogHandler logHandler)
        {
            if (logHandler != null)
            {
                logHandler(“Process() begin”);
            }
            if (logHandler != null)
            {
                logHandler(“Process() end”);
            }
        }
    }
    public class TestApplication
    {
        // Static Function: To which is used in the Delegate. To call the process() function
        static void Logger(string s)
        {
            Console.WriteLine(s);
        }
        static void Main(string[] args)
        {
            // Create an instance of the delegate , pointingto the logging function
            // this delegate will then be passed to the Process() function.
            MyClass myclass = new MyClass();
            MyClass.LogHandler myLogger = new MyClass.LogHandler(Logger);

            myclass.Process(myLogger);
        }
    }
}

จาก Code ข้างต้น หากเรา ทำการ Run ดู ก็จะได้ ผลการทำงาน เป็นอย่างนี้นะครับ

Process() begin
Process() end
ประมาณ นี้ เรามาลองพิจารณา Code กันดูนะครับ ว่า code ข้างต้นทำงานอย่างไร อย่าลืมว่าเรากำลัง ดูตัวอย่างการใช้งาน delegates      ในตัวอย่างนี้ เราจะประกาศ หรือ declare delegates ไว้ใน class ชื่อ MyClass  โดยให้ delegates มีชื่อว่า LogHandler โดยให้มี parameter 1 ตัว เป็น string ใช่ใหมครับ (บรรทัดที่ 5) เมื่อเราประกาศไว้เช่นนี้ นั่นก็หมายถึงว่า Function ที่เราต้องการ ทำ delegate ก็ต้องมี การประกาศในรูปแบบเดียวกัน นะครับ และจากตัวอย่างนี้ แสดงให้เห็น ว่า ตัว function อยู่ที่ไหน ก็ได้ใน namespace เดียวกัน ในตัวอย่างเราวางไว้ใน class TestApplication ซึ่งเป็น class ที่เราใช้เริ่มต้นการทำงาน

ในบรรทัด ที่ 22 – 25 เป็นส่วนที่เรา Implement  function ที่เราต้องการให้เป็น delegates ซึ่งไม่ได้ทำอะไรมากเพียงแต่ นำ parameters ที่ส่งเขามา แสดงผลที่หน้าจอด้วย WriteLine() นะครับ สังเกตุว่า  function นี้ เป็น อะไรครับ ใช้แล้วเป็น static function ด้วย  หลายคนคงพอเข้าใจนะครับ ว่าทำไมต้องทำให้เป็นอย่างนั้น ถามว่า ไม่เป็น static ได้ไหม ตอบว่าได้ แต่ต้องเรียกใช้ผ่าน object ของ TestApplication ใช่ไหมครับ  เพราะมัน เป็น static จึงเรียกใช้มันได้เลย นั่นแหละเป็น เหตุผล ครับ แต่ว่าตรงนี้คงไม่ใช้ประเด็น นะครับ มาดูกัน ครับ

บรรทัดที่ 7 – 18 คือ Function process มี Parameter 1  ตัว เป็นชนิด LogHandler  ซึ่งมันคือ delegates type ที่เราประกาศไว้ เวลาเราใช้งาน delegate เรามองมันคล้าย class หรือ object ก็ได้นะครับ จะไ้ด้สะดวกใจ     นั่นก็คือ function Process(LogHandler logHandler) นั้นรับ parameter เป็น delegate type นั่นเอง  หลังจากนั้น ใน body เป็นการใช้งาน delegates ที่ส่งผ่านเข้าไป ซึ่งการเรียกใช้ ก็เป็นลักษณะนี้

   logHandler("Process() begin");

ก็เป็นการส่ง string ให้กับ function นั่นแหละครับ  มาดูต่อใน Function Main กันนะครับ ที่ function Main นี้เราจะเริ่มใช้งาน ด้วยการ instantiate MyClass หรือ สร้าง object ที่ชื่อ myClass ขึ่นมา  และต่อมาเรา ก็ สร้าง instance ของ delegate โดยเรา ส่งชื่อ function เป็น argument

MyClass.LogHandler myLogger = new MyClass.LogHandler(Logger);

นั่นแหละครับเราก็จะได้ myLogger เป็น object ที่ชี้ไปที่  Logger ครับ เท่านี้เราก็พร้อมที่ส่ง มันไปทำงานที่ไหนก็ได้ตามต้องการ สำหรับตัวอย่างของเรา ส่งกลับไปเป็น Argument ของ  myclass.Process() ดังนี้

myclass.Process(myLogger);

หลังจากนี้ผมคงไม่ต้อง อธิบายต่อนะครับว่ามันเป็นอย่างไรต่อไป

ครับ จากตัวอย่างคงพอจะเห็นการทำงานเพิ่มขึ้นนะครับ ว่า delegate ทำงานอย่างไร  คิดว่าหลายคนยังคงมีคำถามหลาย ๆ คำถามอยู่ในใจ ผมคิดว่าหลาย ๆ คำถามอีกเช่นกัน ท่านสามารถทดลอง หาคำตอบได้ด้วยตนเอง ฮิ ฮิ คือว่าขี้เกียจตั้งคำถามอะครับ

อีกสักตัวอย่างเป็นไงครับ ดูตัวอย่างนี้ดีกว่านะครับ Advance ขึ้นมาอีก

using System.IO;

namespace ConsoleApplication1
{
public class MyClass
{
public delegate void LogHandler(string message);

public void Process(LogHandler logHandler)
{
if (logHandler != null)
{
logHandler(“Process() begin”);
}
if (logHandler != null)
{
logHandler(“Process() end”);
}
}
}
// The FileLogger class merely encapsulates the file I/O
public class FileLogger
{
FileStream fileStream;
StreamWriter streamWriter;

// Constructor
public FileLogger(string filename)
{
fileStream = new FileStream(filename, FileMode.Create);
streamWriter = new StreamWriter(fileStream);
}

// Member Function which is used in the Delegate
public void Logger(string s)
{
streamWriter.WriteLine(s);
}

public void Close()
{
streamWriter.Close();
fileStream.Close();
}
}
public class TestApplication
{
static void Main(string[] args)
{
FileLogger fl = new FileLogger(“process.log”);

MyClass myClass = new MyClass();

// Crate an instance of the delegate, pointing to the Logger()
// function on the fl instance of a FileLogger.
MyClass.LogHandler myLogger = new MyClass.LogHandler(fl.Logger);
myClass.Process(myLogger);
fl.Close();
}
}
}

เอาละครับ หลังจาก ดู code กันแล้วหลายคน คงพอเข้าใจ หลายคนคงถูกใจเพราะตรงกับคำถามในใจจาก ตัวอย่างที่แล้ว ครับในตัวอย่างนี้ เราสร้าง class ใหม่ขึ้นมานะครับ ชื่อว่า FileLogger แล้ว ใน class นี้เราก็มี method สำคัญของเรา คือ Logger เราย้ายมาไว้ใน class นี้เพื่อให้เห็นการทำงานที่แตกต่างออกไปอีก นั้นก็หมายถึงว่า ไม่ว่า function ที่ต้องการใช้เป็น delegate จะอยู่ที่ไหนก็ตาม เราก็สามารถใช้งานมันได้ ครับ ขอเพียงว่าให้เป็นไปตามข้อกำหนดของ การทำ delegates ก็แล้วกัน เอาล่ะครับ ตัวอย่างนี้คงไม่ต้อง พูดกันมากนะครับ เนื่องจากการประกาศ delegates นั้นใช้ของเดิมจากตัวอย่างที่แล้ว แต่ delegate  funciton นั้น อยู่ใน class อีก class หนึ่งและก็ไม่ได้เป็น static method ด้วย ดังนั้นการที่จะเข้าถึง fuction Logger ก็ต้อง ทำผ่าน instance ของ class FileLogger นะครับ ดังนั้นใน Main method จึงได้ instantiate f1 ให้เป็น Object ของ FileLogger ขึ้นมา ซึ่งจะต้องสึ่งชื่อไฟล์ให้กับ Constructor ของ FileLogger ด้วยนะครับ ชื่อ ว่า process.log ตามนี้

FileLogger fl = new FileLogger(“process.log”);

เพื่อให้เราสามารถอ้างอิง เจ้า Logger ได้นั่นเอง หลังจากนั้น เราก็ส่ง  f1.Logger ให้กับ delegates  object ใช่ใหม ครับ แล้วเจ้า instance ของ delegates ก็อ้างอิงมายัง f1.Logger มันก็เหมือนเราเรียกใช้ f1.logger โดยการอ้างอิงผ่านทาง address นั่นเองครับ

MyClass.LogHandler myLogger = new MyClass.LogHandler(fl.Logger);

หลังจากนั้นเราก็ ส่ง  myLogger ให้กับ Process เหมือนเดิมนะครับ แต่ผลการทำงานของ โปรแกรม นี้มันไม่ได้แสดงผลทรี่หน้าจอนะครับ มันส้ราง file และเขียนลง file ลอง พิมพ์ code แล้ว run ดูนะครับ แล้วจะเข้าใจ

จบก่อนนะครับ สำหรับ ตอนต่อไป จะเป็นเรื่อง Multicasting เน่อ   🙂

Categories: C# .NET, DOT NET