Hướng dẫn入门 về Reflection trong C

Xin chào bạn, ngôi sao lập trình tương lai! Hôm nay, chúng ta sẽ bắt đầu một hành trình thú vị vào thế giới Reflection của C#. Đừng lo lắng nếu bạn chưa từng viết một dòng mã trước đây - tôi sẽ là người hướng dẫn thân thiện của bạn, và chúng ta sẽ cùng khám phá chủ đề này từng bước một. Cuối cùng của bài hướng dẫn này, bạn sẽ có một hiểu biết vững chắc về Reflection là gì và cách sử dụng nó. Hãy cùng bắt đầu!

C# - Reflection

Reflection là gì?

Hãy tưởng tượng bạn đang ở một nhà hàng sang trọng, và bạn được đưa một thực đơn. Nhưng đây không phải là bất kỳ thực đơn nào - nó là ma thuật! Không chỉ bạn có thể thấy các món ăn, bạn còn có thể ngó vào bếp để xem chúng được làm như thế nào, nguyên liệu nào được sử dụng, và thậm chí là thay đổi công thức trên máy bay. Đó chính xác là những gì Reflection làm trong C#, nhưng với mã thay vì thức ăn.

Trong thuật ngữ kỹ thuật, Reflection là một tính năng trong C# cho phép một chương trình kiểm tra, tương tác và thay đổi cấu trúc và hành vi của chính nó tại thời điểm chạy. Nó giống như tặng cho chương trình của bạn một tấm gương để nó có thể nhìn vào chính mình!

Ứng dụng của Reflection

Bây giờ, bạn có thể tự hỏi, "Tại sao tôi lại muốn chương trình của mình nhìn vào chính nó?" Câu hỏi tuyệt vời! Hãy cùng khám phá một số ứng dụng thực tế của Reflection:

  1. Tải các tập hợp mã động: Reflection cho phép bạn tải và sử dụng các tập hợp mã (giống như các gói mã) mà không nhất thiết phải biết chúng khi bạn viết chương trình.

  2. Tạo các đối tượng của các loại: Bạn có thể tạo các đối tượng của một loại nào đó mà không biết chính xác loại đó tại thời điểm biên dịch.

  3. Gọi các phương thức: Reflection cho phép bạn gọi các phương thức trên các đối tượng động.

  4. Truy cập và thay đổi các trường và thuộc tính: Bạn có thể đọc và ghi các trường và thuộc tính của một đối tượng.

  5. Kiểm tra các thuộc tính: Bạn có thể kiểm tra các thuộc tính (thông tin bổ sung) gắn với các phần tử khác nhau của chương trình.

Hãy cùng xem xét chi tiết hơn với một số ví dụ mã!

Ví dụ 1: Tạo một đối tượng động

using System;
using System.Reflection;

class Program
{
static void Main()
{
// Lấy loại của lớp string
Type stringType = typeof(string);

// Tạo một đối tượng string sử dụng Reflection
object str = Activator.CreateInstance(stringType, new object[] { "Hello, Reflection!" });

Console.WriteLine(str); // Output: Hello, Reflection!
}
}

Trong ví dụ này, chúng ta đang sử dụng Reflection để tạo một đối tượng của lớp string. Nó giống như nói với C#, "Tôi muốn tạo một thứ, nhưng tôi sẽ nói bạn nó là gì tại thời điểm chạy." Điều này đặc biệt hữu ích khi bạn không biết chính xác loại bạn cần tạo cho đến khi chương trình của bạn đang chạy.

Ví dụ 2: Gọi một phương thức động

using System;
using System.Reflection;

class MyClass
{
public void SayHello(string name)
{
Console.WriteLine($"Hello, {name}!");
}
}

class Program
{
static void Main()
{
// Tạo một đối tượng MyClass
MyClass obj = new MyClass();

// Lấy loại của MyClass
Type type = obj.GetType();

// Lấy MethodInfo cho phương thức SayHello
MethodInfo methodInfo = type.GetMethod("SayHello");

// Gọi phương thức
methodInfo.Invoke(obj, new object[] { "Reflection" });
// Output: Hello, Reflection!
}
}

Ở đây, chúng ta đang sử dụng Reflection để gọi phương thức SayHello trên đối tượng MyClass. Nó giống như chúng ta nói với C#, "Tôi biết đối tượng này có một phương thức名叫 'SayHello', hãy gọi nó giúp tôi." Điều này rất hữu ích khi bạn cần gọi các phương thức trên các đối tượng mà bạn không biết chính xác loại chúng tại thời điểm biên dịch.

Xem thông tin metadata

Một trong những điều thú vị nhất về Reflection là nó cho phép chúng ta nhìn vào bên trong mã của chúng ta. Chúng ta có thể xem thông tin metadata về các loại, phương thức, thuộc tính và nhiều hơn nữa. Hãy cùng xem xét!

Ví dụ 3: Xem thông tin metadata của loại

using System;
using System.Reflection;

class Program
{
static void Main()
{
Type stringType = typeof(string);

Console.WriteLine($"Type Name: {stringType.Name}");
Console.WriteLine($"Full Name: {stringType.FullName}");
Console.WriteLine($"Namespace: {stringType.Namespace}");
Console.WriteLine($"Is it a class? {stringType.IsClass}");
Console.WriteLine($"Base Type: {stringType.BaseType}");

Console.WriteLine("\nMethods:");
foreach (MethodInfo method in stringType.GetMethods())
{
Console.WriteLine(method.Name);
}
}
}

Mã này giống như hỏi lớp string để nó kể cho chúng ta biết tất cả về chính nó. Chúng ta đang tìm hiểu tên của nó, nó thuộc không gian tên nào, liệu nó có phải là một lớp không, nó kế thừa từ lớp nào, và thậm chí liệt kê tất cả các phương thức của nó. Nó giống như có một cuộc trò chuyện với mã của bạn!

Ví dụ tổng quát

Hãy kết hợp tất cả lại với một ví dụ phức tạp hơn để展示 các khía cạnh khác nhau của Reflection:

using System;
using System.Reflection;

public class Person
{
public string Name { get; set; }
public int Age { get; set; }

public Person(string name, int age)
{
Name = name;
Age = age;
}

public void Introduce()
{
Console.WriteLine($"Hi, I'm {Name} and I'm {Age} years old.");
}
}

class Program
{
static void Main()
{
// Tạo một đối tượng Person sử dụng Reflection
Type personType = typeof(Person);
object[] constructorArgs = { "Alice", 30 };
Person person = (Person)Activator.CreateInstance(personType, constructorArgs);

// Lấy và đặt giá trị thuộc tính sử dụng Reflection
PropertyInfo nameProperty = personType.GetProperty("Name");
PropertyInfo ageProperty = personType.GetProperty("Age");

Console.WriteLine($"Current Name: {nameProperty.GetValue(person)}");
nameProperty.SetValue(person, "Bob");
ageProperty.SetValue(person, 25);

// Gọi một phương thức sử dụng Reflection
MethodInfo introduceMethod = personType.GetMethod("Introduce");
introduceMethod.Invoke(person, null);

// Hiển thị tất cả các phương thức của lớp Person
Console.WriteLine("\nMethods of Person class:");
foreach (MethodInfo method in personType.GetMethods())
{
Console.WriteLine(method.Name);
}
}
}

Ví dụ này minh họa việc tạo một đối tượng, lấy và đặt giá trị thuộc tính, gọi phương thức và liệt kê tất cả các phương thức của một lớp, tất cả đều sử dụng Reflection. Nó giống như chúng ta là những người điều khiển, kiểm soát đối tượng Person hoàn toàn thông qua Reflection!

Bảng các phương thức Reflection phổ biến

Dưới đây là bảng các phương thức Reflection phổ biến:

Phương thức Mô tả
Type.GetType() Lấy Type với tên được chỉ định
Object.GetType() Lấy Type của đối tượng hiện tại
Type.GetMethods() Trả về tất cả các phương thức công khai của Type hiện tại
Type.GetProperties() Trả về tất cả các thuộc tính công khai của Type hiện tại
Type.GetFields() Trả về tất cả các trường công khai của Type hiện tại
Type.GetConstructors() Trả về tất cả các constructor công khai của Type hiện tại
Activator.CreateInstance() Tạo một đối tượng của một type
MethodInfo.Invoke() Gọi một phương thức
PropertyInfo.GetValue() Lấy giá trị của một thuộc tính
PropertyInfo.SetValue() Đặt giá trị của một thuộc tính

Kết luận

Uf! Chúng ta đã bao quát rất nhiều nội dung hôm nay. Reflection có thể看起来有点令人困惑, nhưng nó là một công cụ vô cùng mạnh mẽ trong bộ công cụ C# của bạn. Nó cho phép các chương trình của bạn linh hoạt và động hơn, thích ứng với các điều kiện tại thời điểm chạy.

Nhớ rằng, với quyền lực lớn đi kèm với trách nhiệm lớn. Reflection có thể chậm hơn mã trực tiếp và có thể làm gián đoạn tính an toàn của type nếu không được sử dụng cẩn thận. Nhưng khi sử dụng một cách khôn ngoan, nó có thể giải quyết các vấn đề mà sẽ khó khăn hoặc không thể giải quyết bằng các phương pháp khác.

Tiếp tục thực hành, tiếp tục khám phá, và trước khi bạn biết, bạn sẽ thành thạo Reflection! Chúc may mắn, ngôi sao C# tương lai!

Credits: Image by storyset