Bài tập 4(B9_C#) LỚP VALIDATOR

MỤC TIÊU BÀI HỌC

Sau khi hoàn thành bài tập này, bạn sẽ:

  1. ✅ xây dựng lớp Static trong C#

  2. ✅ Xây dựng các phương thức kiểm tra dữ liệu (validation)

  3. ✅ Sử dụng biểu thức chính quy (Regex) để kiểm tra định dạng

  4. ✅ Áp dụng thực hành xử lý ngoại lệ khi validation

  5. ✅ Xây dựng thư viện tiện ích (Utility) dùng chung

SƠ ĐỒ TỔNG QUAN LỚP VALIDATOR

┌─────────────────────────────────────────────────────────────┐
│ LỚP VALIDATOR (STATIC) │
├─────────────────────────────────────────────────────────────┤
│ │
│ 🛠️ PHƯƠNG THỨC STATIC │
│ │
│ 📧 Kiểm tra Email │
│ └── IsValidEmail(string email) : bool │
│ │
│ 📱 Kiểm tra Số điện thoại │
│ └── IsValidPhone(string phone) : bool │
│ │
│ 📅 Kiểm tra Ngày tháng │
│ └── IsValidDate(string date, out DateTime result) : bool │
│ │
│ 🔢 Kiểm tra Số trong khoảng │
│ └── IsInRange<T>(T value, T min, T max) : bool │
│ │
│ 📝 Kiểm tra Chuỗi không rỗng │
│ └── IsNotEmpty(string str) : bool │
│ │
│ 📏 Kiểm tra Độ dài chuỗi │
│ └── IsValidLength(string str, int min, int max) : bool │
│ │
└─────────────────────────────────────────────────────────────┘

BƯỚC 1: TẠO PROJECT MỚI

1.1. Mở Visual Studio

  • Mở Visual Studio 2022

1.2. Tạo Project mới

text
File → New → Project

Hoặc nhấn: Ctrl + Shift + N

1.3. Chọn loại Project

  • Gõ “Console” vào ô tìm kiếm

  • Chọn Console App (.NET Core) hoặc Console App (.NET Framework)

  • Nhấn Next

1.4. Đặt tên Project

text
Project name: Bai4_Validator
Location: D:\CSharp\LapTrinhHuongDoiTuong
Solution: LapTrinhHuongDoiTuong (chọn Add to Solution)
  • Nhấn Next

1.5. Chọn Framework

  • Chọn .NET 6.0 hoặc .NET 8.0 (LTS)

  • Nhấn Create

BƯỚC 2: TẠO CẤU TRÚC THƯ MỤC

2.1. Tạo thư mục Helpers

  1. Trong Solution Explorer, click chuột phải vào Project Bai4_Validator

  2. Chọn Add → New Folder

  3. Đặt tên: Helpers

  4. Nhấn Enter

BƯỚC 3: TẠO FILE LỚP VALIDATOR

3.1. Tạo file Validator.cs

  1. Click chuột phải vào thư mục Helpers

  2. Chọn Add → Class

  3. Đặt tên: Validator.cs

  4. Nhấn Add

BƯỚC 4: VIẾT CODE CHO LỚP VALIDATOR

4.1. Khai báo Namespace và Class Static

Mở file Validator.cs và viết:

csharp
using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace Bai4_Validator.Helpers
{
    public static class Validator
    {
        // Code sẽ viết ở đây
    }
}

Lưu ý quan trọng:

  • Dùng public static class → Lớp không thể khởi tạo

  • Tất cả phương thức đều là public static

4.2. Phương thức 1: Kiểm tra Email

csharp
public static class Validator
{
    // === PHƯƠNG THỨC KIỂM TRA EMAIL ===
    
    /// <summary>
    /// Kiểm tra email có đúng định dạng hay không
    /// </summary>
    public static bool IsValidEmail(string email)
    {
        // 1. Kiểm tra email không được rỗng
        if (string.IsNullOrWhiteSpace(email))
            return false;
        
        try
        {
            // 2. Dùng lớp MailAddress để kiểm tra
            var addr = new System.Net.Mail.MailAddress(email);
            return addr.Address == email;
        }
        catch
        {
            return false;
        }
    }
}

4.3. Phương thức 2: Kiểm tra Số điện thoại

csharp
    // === PHƯƠNG THỨC KIỂM TRA SỐ ĐIỆN THOẠI ===
    
    /// <summary>
    /// Kiểm tra số điện thoại Việt Nam (10 số, đầu 03/05/07/08/09)
    /// </summary>
    public static bool IsValidPhone(string phone)
    {
        // 1. Kiểm tra không rỗng
        if (string.IsNullOrWhiteSpace(phone))
            return false;
        
        // 2. Kiểm tra độ dài đúng 10 số
        if (phone.Length != 10)
            return false;
        
        // 3. Kiểm tra tất cả đều là số
        if (!phone.All(char.IsDigit))
            return false;
        
        // 4. Kiểm tra đầu số hợp lệ (03, 05, 07, 08, 09)
        string[] prefixes = { "03", "05", "07", "08", "09" };
        return prefixes.Any(p => phone.StartsWith(p));
    }

Cách dùng Regex (biểu thức chính quy):

csharp
// Có thể dùng Regex để kiểm tra nhanh hơn
public static bool IsValidPhoneRegex(string phone)
{
    if (string.IsNullOrWhiteSpace(phone)) return false;
    // Mẫu: 10 số, bắt đầu 03/05/07/08/09
    string pattern = @"^(03|05|07|08|09)\d{8}$";
    return Regex.IsMatch(phone, pattern);
}

4.4. Phương thức 3: Kiểm tra Ngày tháng

csharp
    // === PHƯƠNG THỨC KIỂM TRA NGÀY THÁNG ===
    
    /// <summary>
    /// Kiểm tra chuỗi có đúng định dạng ngày tháng dd/MM/yyyy không
    /// </summary>
    public static bool IsValidDate(string date, out DateTime result)
    {
        // out result: Trả về giá trị DateTime nếu hợp lệ
        return DateTime.TryParseExact(
            date,
            "dd/MM/yyyy",
            System.Globalization.CultureInfo.InvariantCulture,
            System.Globalization.DateTimeStyles.None,
            out result
        );
    }

.5. Phương thức 4: Kiểm tra số trong khoảng

csharp
    // === PHƯƠNG THỨC KIỂM TRA SỐ TRONG KHOẢNG ===
    
    /// <summary>
    /// Kiểm tra giá trị có nằm trong khoảng [min, max] hay không
    /// </summary>
    /// <typeparam name="T">Kiểu dữ liệu (int, double, decimal...)</typeparam>
    public static bool IsInRange<T>(T value, T min, T max) where T : IComparable<T>
    {
        return value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0;
    }

Giải thích Generic:

  • <T>: Cho phép dùng với nhiều kiểu dữ liệu (int, double, decimal…)

  • where T : IComparable<T>: Đảm bảo kiểu T có thể so sánh

  • value.CompareTo(min) >= 0: value >= min

4.6. Phương thức 5: Kiểm tra chuỗi không rỗng

csharp
    // === PHƯƠNG THỨC KIỂM TRA CHUỖI KHÔNG RỖNG ===
    
    /// <summary>
    /// Kiểm tra chuỗi không rỗng hoặc chỉ có khoảng trắng
    /// </summary>
    public static bool IsNotEmpty(string str)
    {
        return !string.IsNullOrWhiteSpace(str);
    }

4.7. Phương thức 6: Kiểm tra độ dài chuỗi

csharp
    // === PHƯƠNG THỨC KIỂM TRA ĐỘ DÀI CHUỖI ===
    
    /// <summary>
    /// Kiểm tra độ dài chuỗi nằm trong khoảng [min, max]
    /// </summary>
    public static bool IsValidLength(string str, int min, int max)
    {
        if (str == null) return false;
        return str.Length >= min && str.Length <= max;
    }

4.8. Phương thức 7: Kiểm tra số nguyên

csharp
    // === PHƯƠNG THỨC KIỂM TRA SỐ NGUYÊN ===
    
    /// <summary>
    /// Kiểm tra chuỗi có phải là số nguyên không
    /// </summary>
    public static bool IsInteger(string str)
    {
        if (string.IsNullOrWhiteSpace(str)) return false;
        return int.TryParse(str, out _);
    }
    
    /// <summary>
    /// Kiểm tra chuỗi có phải là số nguyên dương không
    /// </summary>
    public static bool IsPositiveInteger(string str)
    {
        if (!IsInteger(str)) return false;
        int value = int.Parse(str);
        return value > 0;
    }

4.9. Phương thức 8: Kiểm tra số thực

csharp
    // === PHƯƠNG THỨC KIỂM TRA SỐ THỰC ===
    
    /// <summary>
    /// Kiểm tra chuỗi có phải là số thực (double) không
    /// </summary>
    public static bool IsNumber(string str)
    {
        if (string.IsNullOrWhiteSpace(str)) return false;
        return double.TryParse(str, out _);
    }
    
    /// <summary>
    /// Kiểm tra chuỗi có phải là số thực dương không
    /// </summary>
    public static bool IsPositiveNumber(string str)
    {
        if (!IsNumber(str)) return false;
        double value = double.Parse(str);
        return value > 0;
    }

4.10. Phương thức 9: Kiểm tra mật khẩu mạnh (ít nhất 1 chữ hoa, 1 số, 1 ký tự đặc biệt)

// 9. Kiểm tra mật khẩu mạnh (ít nhất 1 chữ hoa, 1 số, 1 ký tự đặc biệt)
        public static bool IsStrongPassword(string password)
        {
            if (string.IsNullOrWhiteSpace(password) || password.Length < 8)
                return false;
            
            bool hasUpper = password.Any(char.IsUpper);
            bool hasLower = password.Any(char.IsLower);
            bool hasDigit = password.Any(char.IsDigit);
            bool hasSpecial = password.Any(ch => !char.IsLetterOrDigit(ch));
            
            return hasUpper && hasLower && hasDigit && hasSpecial;
        }

BƯỚC 5: VIẾT CHƯƠNG TRÌNH KIỂM TRA (TEST)

5.1. Mở file Program.cs

Trong Solution Explorer, mở file Program.cs của Project Bai4_Validator.

5.2. Viết code test

csharp
using System;
using Bai4_Validator.Helpers;

namespace Bai4_Validator
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;
            Console.WriteLine("===== BÀI TẬP 4: LỚP VALIDATOR =====\n");

            // ============================================
            // TEST 1: Kiểm tra Email
            // ============================================
            Console.WriteLine("1. Kiểm tra Email:");
            TestEmail("admin@gmail.com");
            TestEmail("user@company.vn");
            TestEmail("invalid-email");
            TestEmail("missing@dot");
            TestEmail("");

            // ============================================
            // TEST 2: Kiểm tra Số điện thoại
            // ============================================
            Console.WriteLine("\n2. Kiểm tra Số điện thoại:");
            TestPhone("0987654321");
            TestPhone("0912345678");
            TestPhone("0123456789");
            TestPhone("1234567890");
            TestPhone("098765432");

            // ============================================
            // TEST 3: Kiểm tra Ngày tháng
            // ============================================
            Console.WriteLine("\n3. Kiểm tra Ngày tháng:");
            TestDate("25/12/2024");
            TestDate("01/01/2025");
            TestDate("32/12/2024");
            TestDate("25/13/2024");
            TestDate("25-12-2024");

            // ============================================
            // TEST 4: Kiểm tra số trong khoảng
            // ============================================
            Console.WriteLine("\n4. Kiểm tra số trong khoảng:");
            TestRange(5, 0, 10);
            TestRange(15, 0, 10);
            TestRange(3.5, 0.0, 10.0);
            TestRange(-1, 0, 10);

            // ============================================
            // TEST 5: Kiểm tra chuỗi không rỗng
            // ============================================
            Console.WriteLine("\n5. Kiểm tra chuỗi không rỗng:");
            TestNotEmpty("Hello");
            TestNotEmpty("");
            TestNotEmpty("   ");
            TestNotEmpty(null);

            // ============================================
            // TEST 6: Kiểm tra độ dài chuỗi
            // ============================================
            Console.WriteLine("\n6. Kiểm tra độ dài chuỗi:");
            TestLength("Hello", 2, 10);
            TestLength("Hello", 6, 10);
            TestLength("This is a long string", 5, 10);

            // ============================================
            // TEST 7: Kiểm tra số nguyên
            // ============================================
            Console.WriteLine("\n7. Kiểm tra số nguyên:");
            TestInteger("123");
            TestInteger("123.5");
            TestInteger("-123");
            TestInteger("abc");

            // ============================================
            // TEST 8: Kiểm tra số thực
            // ============================================
            Console.WriteLine("\n8. Kiểm tra số thực:");
            TestNumber("123.45");
            TestNumber("123");
            TestNumber("-123.45");
            TestNumber("abc");

            // ============================================
            // TEST 9: Kiểm tra mật khẩu mạnh
            // ============================================
            Console.WriteLine("\n9. Kiểm tra mật khẩu mạnh:");
            TestPassword("Abc123!@");
            TestPassword("weak");
            TestPassword("NOKHONGCOSO");
            TestPassword("khongcokitudacbiet123");

            Console.WriteLine("\nNhấn phím bất kỳ để thoát...");
            Console.ReadKey();
        }

        // === CÁC HÀM TEST ===

        static void TestEmail(string email)
        {
            bool isValid = Validator.IsValidEmail(email);
            Console.WriteLine($"   Email: '{email}' → {(isValid ? "✓ Hợp lệ" : "✗ Không hợp lệ")}");
        }

        static void TestPhone(string phone)
        {
            bool isValid = Validator.IsValidPhone(phone);
            Console.WriteLine($"   SĐT: '{phone}' → {(isValid ? "✓ Hợp lệ" : "✗ Không hợp lệ")}");
        }

        static void TestDate(string date)
        {
            if (Validator.IsValidDate(date, out DateTime result))
                Console.WriteLine($"   Ngày: '{date}' → ✓ Hợp lệ ({result:dd/MM/yyyy})");
            else
                Console.WriteLine($"   Ngày: '{date}' → ✗ Không hợp lệ");
        }

        static void TestRange<T>(T value, T min, T max) where T : IComparable<T>
        {
            bool isValid = Validator.IsInRange(value, min, max);
            Console.WriteLine($"   {value} trong [{min}, {max}] → {(isValid ? "✓ Hợp lệ" : "✗ Không hợp lệ")}");
        }

        static void TestNotEmpty(string str)
        {
            bool isValid = Validator.IsNotEmpty(str);
            string display = str == null ? "null" : $"'{str}'";
            Console.WriteLine($"   {display}{(isValid ? "✓ Hợp lệ" : "✗ Không hợp lệ")}");
        }

        static void TestLength(string str, int min, int max)
        {
            bool isValid = Validator.IsValidLength(str, min, max);
            Console.WriteLine($"   '{str}' (độ dài: {str?.Length ?? 0}) trong [{min}, {max}] → {(isValid ? "✓ Hợp lệ" : "✗ Không hợp lệ")}");
        }

        static void TestInteger(string str)
        {
            bool isValid = Validator.IsInteger(str);
            Console.WriteLine($"   '{str}' → {(isValid ? "✓ Là số nguyên" : "✗ Không phải số nguyên")}");
        }

        static void TestNumber(string str)
        {
            bool isValid = Validator.IsNumber(str);
            Console.WriteLine($"   '{str}' → {(isValid ? "✓ Là số thực" : "✗ Không phải số thực")}");
        }

        static void TestPassword(string password)
        {
            bool isValid = Validator.IsStrongPassword(password);
            Console.WriteLine($"   '{password}' → {(isValid ? "✓ Mật khẩu mạnh" : "✗ Mật khẩu yếu")}");
        }
    }
}

BƯỚC 6: CHẠY CHƯƠNG TRÌNH

6.1. Build Project

  • Nhấn Ctrl + Shift + B để biên dịch

6.2. Chạy chương trình

  • Nhấn F5 để chạy (Debug mode)

  • Hoặc Ctrl + F5 để chạy không debug


KẾT QUẢ DỰ KIẾN

text
===== BÀI TẬP 4: LỚP VALIDATOR =====

1. Kiểm tra Email:
   Email: 'admin@gmail.com' → ✓ Hợp lệ
   Email: 'user@company.vn' → ✓ Hợp lệ
   Email: 'invalid-email' → ✗ Không hợp lệ
   Email: 'missing@dot' → ✗ Không hợp lệ
   Email: '' → ✗ Không hợp lệ

2. Kiểm tra Số điện thoại:
   SĐT: '0987654321' → ✓ Hợp lệ
   SĐT: '0912345678' → ✓ Hợp lệ
   SĐT: '0123456789' → ✗ Không hợp lệ
   SĐT: '1234567890' → ✗ Không hợp lệ
   SĐT: '098765432' → ✗ Không hợp lệ

3. Kiểm tra Ngày tháng:
   Ngày: '25/12/2024' → ✓ Hợp lệ (25/12/2024)
   Ngày: '01/01/2025' → ✓ Hợp lệ (01/01/2025)
   Ngày: '32/12/2024' → ✗ Không hợp lệ
   Ngày: '25/13/2024' → ✗ Không hợp lệ
   Ngày: '25-12-2024' → ✗ Không hợp lệ

4. Kiểm tra số trong khoảng:
   5 trong [0, 10] → ✓ Hợp lệ
   15 trong [0, 10] → ✗ Không hợp lệ
   3.5 trong [0, 10] → ✓ Hợp lệ
   -1 trong [0, 10] → ✗ Không hợp lệ

5. Kiểm tra chuỗi không rỗng:
   'Hello' → ✓ Hợp lệ
   '' → ✗ Không hợp lệ
   '   ' → ✗ Không hợp lệ
   null → ✗ Không hợp lệ

6. Kiểm tra độ dài chuỗi:
   'Hello' (độ dài: 5) trong [2, 10] → ✓ Hợp lệ
   'Hello' (độ dài: 5) trong [6, 10] → ✗ Không hợp lệ
   'This is a long string' (độ dài: 22) trong [5, 10] → ✗ Không hợp lệ

7. Kiểm tra số nguyên:
   '123' → ✓ Là số nguyên
   '123.5' → ✗ Không phải số nguyên
   '-123' → ✓ Là số nguyên
   'abc' → ✗ Không phải số nguyên

8. Kiểm tra số thực:
   '123.45' → ✓ Là số thực
   '123' → ✓ Là số thực
   '-123.45' → ✓ Là số thực
   'abc' → ✗ Không phải số thực

9. Kiểm tra mật khẩu mạnh:
   'Abc123!@' → ✓ Mật khẩu mạnh
   'weak' → ✗ Mật khẩu yếu
   'NOKHONGCOSO' → ✗ Mật khẩu yếu
   'khongcokitudacbiet123' → ✗ Mật khẩu yếu

Nhấn phím bất kỳ để thoát...

BÀI TẬP VỀ NHÀ MỞ RỘNG

  1. Thêm phương thức IsValidUrl(string url) kiểm tra URL hợp lệ

  2. Thêm phương thức IsValidPassword(string password, int minLength, bool requireSpecial)

  3. Thêm phương thức IsValidDateRange(DateTime start, DateTime end) kiểm tra khoảng ngày hợp lệ

  4. Thêm phương thức IsValidIdentityNumber(string id) kiểm tra CCCD/CMND (12 số)

  5. Viết chương trình nhập thông tin người dùng và validate bằng Validator