เนื่องจากภาษา C# และ Java เป็นภาษา Static Type (C# ตั้งแต่ version 4 มี dynamic ให้ใช้ แต่ไม่ขอกล่าวในที่นี้)
การจะใช้งาน property method ของ object ใดๆ เราก็ต้องเขียนไว้ตั้งแต่ตอน compile time
ตัวอย่างการใช้งาน C# property method แบบทั่วไป
สร้าง class user มี property FirstName, LastName และ method GetFullName
namespace CodeSanook.Examples.CSharp.Reflections
{
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string GetFullName()
{
return $"{FirstName} {LastName}";
}
}
}
เมื่อจะเรียกใช้งาน class User ในตัวอย่างนี้ ผมเขียนอยู่ในรูปแบบของ XUnit unit test project
using CodeSanook.Examples.CSharp.Reflections;
using System.Reflection;
using Xunit;
namespace CodeSanook.Examples.CSharp.Tests.Reflections
{
public class UserTests
{
[Fact]
public void GetFullName_ValidPropertyValues_ReturnCorrectFullName()
{
var user = new User();
user.FirstName = "Anthony";
user.LastName = "CodeSanook";
var fulllName = user.GetFullName();
Assert.Equal("Anthony CodeSanook", fulllName);
}
}
}
จะเห็นได้ว่าการจะเรียกใช้งาน property หรือ method ได้เราต้องใช้งานผ่าน . syntax เท่านั้น ซึ่งหมายความว่าเราต้องรู้แน่นอนแล้วว่าเราจะเรียกใช้ property หรือ method ที่ชื่อว่าอะไร
สำหรับการใช้งานใน Java ก็เป็นแบบทำนองเดียวกันครับ แต่ใน Java เราจะใช้ getter setter method แทน
package com.codesanook.examples.reflection;
public class User {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFullName(){
return String.format("%s %s", this.firstName, this.lastName);
}
}
การใช้งาน class User ในภาษา Java
package com.codesanook.examples.reflection.tests
import com.codesanook.examples.reflection.User
import spock.lang.Specification
import java.lang.reflect.*
class UserTests extends Specification {
def "getFullName should return correct full name"() {
given:
def user =new User()
user.setFirstName("Anthony")
user.setLastName("CodeSanook")
when:
def result = user.getFullName()
then:
result == "Anthony CodeSanook"
}
ทีนี้ ถ้าเราต้องการสร้าง program ให้เกิดความยืดหยุ่น เช่น เราต้องการ ที่จะเรียกใช้ property หรือ method ด้้วย string จะต้องทำอย่างไร นี่จึงเป็นที่มาของ reflection ในภาษา C# และ Java ที่ทำให้เราสามารถเรียกใช้ property หรือ method ตอน run time ได้เลย
อีกทั้งเราสามารถเข้าไปวน loop ดู property fields attribute etc ก็ได้
ตัวอย่างที่มีการนำไปใช้ เช่น
code ตัวอย่างต่อไปจะแสดงการใช้งาน reflection แบบง่ายๆ ใน ภาษา C# และ Java ครับ
ตัวอย่างภาษา C#
[Fact]
public void GetFullNameWithReflection_ValidPropertyValues_ReturnCorrectFullName()
{
var user = new User();
var userType = user.GetType();
var firstNameProperty = userType.GetProperty("FirstName");
var lastNameProperty = userType.GetProperty("LastName");
firstNameProperty.SetValue(user, "Anthony");
lastNameProperty.SetValue(user, "CodeSanook");
var getfullNameMethod = userType.GetMethod("GetFullName");
var fullName = getfullNameMethod.Invoke(user, null);
Assert.Equal("Anthony CodeSanook", fullName);
}
ตัวอย่างภาษา Java
def "invoke getFullName method with Reflection should return correct full name"() {
given:
def user = new User()
user.setFirstName("Anthony")
user.setLastName("CodeSanook")
when:
Class userClass = user.getClass()
Method method = userClass.getMethod("getFullName")
def fullName = method.invoke(user, null)
then:
fullName == "Anthony CodeSanook"
}
def "getDeclaredMethods with Reflection should return 5 method"() {
given:
def user = new User()
when:
Class userClass = user.getClass();
Method[] methods = userClass.getDeclaredMethods();
then:
methods.length == 5
}
reflect ยังมี API ให้ใช้งาน และประยุกต์ใช้ได้อีกมากครับ แต่ในตัวอย่างนี้ ขอนำเสนอแบบเบื้องต้นเพื่อให้ผู้อ่านได้เห็นภาพ เพราะหากผู้อ่านได้เขียน program ไปสักพักจะพบว่าจะมีเหตุการณ์ให้เราสามารถนำส่วนนี้ไปประยุกต์ใช้ได้ รวมถึงเมื่อเข้าไปอ่าน source code opensource ต่างๆ เมื่อเห็นส่วนนี้ เราก็จะทำความเข้าใจได้ง่าย
แต่ reflection ก็ไม่ควรหากไม่จำเป็นนะครับ เพราะมีผลต่อ performance
source code ของ project นี้นะครับ
https://github.com/aaronamm/CodeSanook.Examples
ใน source code project นี้มีตัวอย่างที่น่าสนใจครับ ผมใช้ Travis CI ที่ build ทั้ง Java และ C# ร่วมกัน น่าจะมีประโยชน์สำหรับท่านที่ต้องการใช้ Travis เพื่อ support project แบบ multiple languages ครับผม
Travis CI build status