Showing posts with label Coding. Show all posts
Showing posts with label Coding. Show all posts

Monday, January 14, 2013

Event Source Installer และ installutil command

เมื่อ solution ที่เราเขียน ต้องการการติดตั้งบางอย่างบนเครื่องที่เราจะใช้รัน เราสามารถสร้าง installer เพื่อทำการเตรียน Environment ให้โปรแกรมเราได้ เช่นตัวอย่างจะใช้สร้าง Event Source เพื่อใช้เก็บ Event Log

1. สร้าง class ที่ implement Installer ใน solution ที่เราเขียน

using System;
using System.Configuration.Install;
using System.Diagnostics;
using System.ComponentModel;

[RunInstaller(true)]
public class MyEventLogInstaller: Installer
{
    private EventLogInstaller myEventLogInstaller;

    public MyEventLogInstaller() 
    {
        // Create an instance of an EventLogInstaller.
        myEventLogInstaller = new EventLogInstaller();

        // Set the source name of the event log.
        myEventLogInstaller.Source = "NewLogSource";

        // Set the event log that the source writes entries to.
        myEventLogInstaller.Log = "MyNewLog";

        // Add myEventLogInstaller to the Installer collection.
        Installers.Add(myEventLogInstaller);   
    }
}


2. หลังจาก build จะได้ assembly .exe หรือ .dll เราก็สามารถใช้ ตัว VisualStudio Command prompt ติดตังตัว event source ลงบนเครื่องที่เราต้องการได้โดย run as admin แล้วรันคำสั่งต่อไปนี้



C:\xxx\bin>installutil App_Code.dll



3. ตัวอย่างผลรัน


C:\xxx\bin>installutil App_Code.dll
Microsoft (R) .NET Framework Installation utility Version 4.0.30319.17929
Copyright (C) Microsoft Corporation.  All rights reserved.


Running a transacted installation.

Beginning the Install phase of the installation.
See the contents of the log file for the C:\xxx\bin\App_Code.dll assembly's progress.
The file is located at C:\xxx\bin\App_Code.InstallLog.
Installing assembly 'C:\xxx\bin\App_Code.dll'.
Affected parameters are:
   logtoconsole =
   logfile = C:\xxx\bin\App_Code.InstallLog
   assemblypath = C:\xxx\bin\App_Code.dll
Creating EventLog source SemanticLoggingEventLogPerfTests in log ...

The Install phase completed successfully, and the Commit phase is beginning.
See the contents of the log file for the C:\xxx\bin\App_Code.dll assembly's progress.
The file is located at C:\xxx\bin\App_Code.Install
Log.
Committing assembly 'C:\xxx\bin\App_Code.dll'.
Affected parameters are:
   logtoconsole =
   logfile = C:\xxx\bin\App_Code.InstallLog
   assemblypath = C:\xxx\bin\App_Code.dll

The Commit phase completed successfully.

The transacted install has completed.


Saturday, January 12, 2013

ตัวอย่าง match regex แล้ว assign ใส่ groups


ตัดมาจาก code ในส่วยที่เคยใช้ไป get ราคาหุ้น

    this.Html = HttpRequester.RequestHttp(string.Format(this.RequestUrl, tickerSymbol), out errorCode);
    if (errorCode < 0)
    {
        return errorCode;
    }
    string RegexPricePattern = @"<span class=""time_rtq_ticker""><span id=""[^>\t\r\n\v\f]*"">(?<price>\d*\.\d*)</span>?";
    Regex priceFinder = new Regex(RegexPricePattern, RegexOptions.IgnoreCase);
    Match priceMatch = priceFinder.Match(this.Html);
    if (priceMatch.Success)
    {
        string priceString = priceMatch.Groups["price"].Value;
    }


Tuesday, January 8, 2013

new modifier, static binding และ dynamic binding

ในตอนนี้จะพยายเขียนให้เข้าใจง่ายที่สุด สำหรับผู้ที่เพิ่งเริ่มให้เข้าใจกระบวนการ instantiate object

คำสั่งในภาษา C# เช่นคำสั่ง new อาจมีการใช้งานได้เกินหนึ่งรูปแบบซึ่งก็คือ
  1. ใช้ในการทำ method hiding
  2. ใช้สร้าง object
ในหัวข้อนี้ เราจะขอพูดถึงอย่างหลังก่อนนะครับแล้วในตอนท้าย จะค่อยสาธิตการทำ method hinding

ในการสร้าง object เราสามารถใช้คำสั่งแบบนี้

    new Beer();


จะเห็นว่า หลังคำว่า new จะเป็นชื่อของ constructor ของ class ที่เราต้องการสร้าง นั้นก็คือ Beer() ซึ่ง constructor คือ method ของ class ที่จะทำงานเมือเราต้องการจะสร้าง class นั้นๆ เช่น class Beer ข้างล่าง


    class Beer
    {
        String Name;

        public Beer() : this("Noname")
        {
        }

        public Beer(string name)
        {
            this.Name = name;
        }
    }


จะเห็นว่า ใน class Beer มีสอง method ที่ไม่มี return type และมีชื่อเหมือนกันกับชื่อ class คือ "Beer()" และ "Beer(string name)" (constructor overload) นั้นหมายความว่า เราสามารถสร้าง object จาก constructor ตัวใดตัวหนึ่งจากสองตัวนี้ก็ได้ ทำให้การสร้าง object มีความยืดหยุ่น และสามารถประยุคเทคนิคในการสร้างและจัดการ object ได้หลากหลาย

จากตัวอยากข้างบน "new Beer()" code จะทำงานดังนี้

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       8 (0x8)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  newobj     instance void SampleDynamicBinding.Beer::.ctor()
  IL_0006:  pop
  IL_0007:  ret
} // end of method Program::Main


ข้างบนนี้คือ MSIL ที่ได้หลังจาก compile คำสั่ง new Beer(); การทำงานคร่าวๆ ก็คือ
  1. เรียก constructor เพื่อสร้าง instance ของ class Beer
  2. จองและจัดสรรนหน่วยความจำ เพื่อเก็บ instance ของ Beer ในที่นี้คือ managed heap
  3. จบ

อ่าว แล้วงี้เราจะไปใช้ไอ้ตัว object นี้ได้ไงอ่ะ คำตอบคือ เราก็สร้างตัวแปร เพื่อที่จะอ้างอิงไปหาไอ้ instance ที่อยู่ใน heap นั้นไงล่ะ, ง่ายๆ ด้วย syntax ที่คุ้นเคย แบบนี้

    Beer beer = new Beer();


จะเห็นว่า มีส่วนเพิ่มขึ้นมาสามส่วนจากหน้าไปหลังคือ
  1. Beer คือ ชื่อของ type นั้นก็คือ class Beer ซึ่งต้องมี type ตรงกันกับกับ object ที่เราสร้างด้วยคำสั่ง new
  2. beer คือชือของตัวแปร
  3. เครื่องหมาย "=" คือการ assign ค่าอ้างอิงไปยัง instance ของ Beer ที่เราสร้างดังที่อธิบายไปแล้ว

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       8 (0x8)
  .maxstack  1
  .locals init ([0] class SampleDynamicBinding.Beer beer)
  IL_0000:  nop
  IL_0001:  newobj     instance void SampleDynamicBinding.Beer::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ret
} // end of method Program::Main


MSIL ที่ compile ออกมาจะต่างออกไปหน่อย ซึ่งการทำงานคร่าวๆ จะเป็นประมาณนี้

  1. หลังจากที่มีการสร้าง instance ของ class และเก็บไว้ใน managed heap ไปแล้ว
  2. จองเนื้อที่ใน stack เพื่อเก็บตัวแปร "beer" ซึ่งมี type เป็น Beer
  3. ทำการกำหนดค่า reference ของ beer ไปยัง instance ในข้อ 1.
ทีนี้ เราก็สามารถใช้ instance ของ class Beer ได้แล้ว โดยการใช้ผ่านตัวแปร beer นั้นเอง ซึ่งการกำหนดค่าอ้างอิงของ instance ไปยังตัวแปรที่มี type ตรงกัน เราเรียกว่า name binding 

การ binding แบ่งออกเป็น 2 แบบคือ static binding และ dynamic binding
  1. Static binding คือ การ กำหนดค่าอ้างอิงไปยังตัวแปลได้เลย ขณะ compile time ดังตัวอย่างข้างต้น
  2. Dynamic binding คือ การกำหนดค่าอ้างอิงไปยังตัวแปลของ object ขณะ run-time ซึ่งวิธีนี้ ทำให้การออกแบบซอร์ฟแวรได้ยืดหยุ่น และหลากหลาย สนับสนุนหลักการ polymorphism เช่น dependency injection เป็นต้น
ตัวอย่างด้านล่าง จะเป็นการสาธิตการทำ dynamic binding และการทำ method hiding ด้วย new modifier นะครับ จาก class Beer เราจะเพิ่ม class ที่ชือว่า Singha เข้ามา ซึ่งนี้ implement class Beer อยู่ (inherit) 

    class Beer
    {
        string Name;

        public Beer() : this("Noname")
        {
        }

        public Beer(string name)
        {
            this.Name = name;
        }

        public void WriteName()
        {
            Console.WriteLine(this.Name);
        }
    }

    class Singha : Beer
    {
        string Name; 

        public Singha() : this("Singha")
        {
        }

        public Singha(string name)
        {
            this.Name = name;
        }

        public new void WriteName()
        {
            Console.WriteLine(this.Name);
        }
    }


บรรทัดข้างล่างนี้ เป็นการสร้าง instance ของ class Singha แล้ว assign ใส่ตัวแปลที่ชื่อว่า beer ซึ่งมี type เป็น Singha

    Singha beer = new Singha();


ซึ่งกระบวนการสร้าง object แบบนี้จะต่างจากแบบก่อนหน้านิดหน่อย เพราะว่า class Singha implement class Beer ทำให้เวลาสร้าง object Singha ใน heap จะมีการสร้างและเรียก constructor ของ class แม่มันด้วย ซึ่งก็คือ Beer ทำให้ใน managed heap มี instance อยู่สองตัว คือ
  1. instance ของ class Singha
  2. instance ของ class Beer
นั้นหมายความว่า ถ้าเราใช้ตัวแปร เป็น type ของ Beer เราก็สามารถที่จะเลือกเสียบไปยัง instance Singha หรือ Beer ใน heap ก็ได้ ซึ่งนั้นก็คือ dynamic binding เป็นผลเนื่องมาจาก compiler มีการทำ implicit type conversion

    Beer beer = new Singha();


แต่เราไม่สามารถทำแบบนี้ได้

    Singha beer = new Beer();


เพราะว่า เราเรียก constructor ของ Beer จะไม่มีการสร้าง instance ของ class Singha, การทำ type conversion จะเป็นจาก base class ไป derived class เท่านั้น  ไม่งั้นจะเกิด error แบบนี้
Cannot implicitly convert type 'SampleDynamicBinding.Beer' to 'SampleDynamicBinding.Singha'. An explicit conversion exists (are you missing a cast?)

ตัวอย่าง

    Singha beer = new Singha();
    beer.WriteName();               // dynamic type คือ Singha
    ((Beer)beer).WriteName();       // dynamic type คือ Beer


ผลรัน


    Singha
    Noname

นอกจาก method hiding ก็ยังมีการทำ method overriding อีกตัว ซึงเป็นการเปลี่ยนการทำงานของ method ใน derived class ต่างจากการทำ hiding ที่จะทับการทำงานเดิม

ตัวอย่าง

    Beer beer = new Singha();
    beer.WriteName();               // dynamic type คือ Singha
    ((Beer)beer).WriteName();       // dynamic type คือ Beer


ผลรัน

    Noname
    Noname

ผลรันเป็น Noname ทั้งสองบรรทัดเนื่องจาก class Singha มีการทำ method hinding ทำให้ complier มองเป็นคนละ method กัน ถึงแม้จะเรียกใช้ constructor ของ Singha ซึ่งจะมีการ  implicit type conversion จาก Beer เป็น Singha แต่ method ที่ถูกเรียกจะเป็น Beer.WriteName() 

ตัวอย่างด้านล่างคือการทำ method overriding

    class Beer
    {
        string Name;

        public Beer() : this("Noname")
        {
        }

        public Beer(string name)
        {
            this.Name = name;
        }

        public virtual void WriteName()
        {
            Console.WriteLine(this.Name);
        }
    }

    class Singha : Beer
    {
        string Name; 

        public Singha() : this("Singha")
        {
        }

        public Singha(string name)
        {
            this.Name = name;
        }

        public override void WriteName()
        {
            Console.WriteLine(this.Name);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Beer beer = new Singha();
            beer.WriteName();               
            ((Beer)beer).WriteName();       
        }
    }
 

ผลรัน


    Singha
    Singha

จะเห็นว่าการทำ method overriding จะเป็นการทับการทำงานของ method เดิม