میخوایم این منطق رو سوار بر clean arc کنیم

چک لیست برای سفر میخوایم داشته باشیم

اول میایم یه blank soultion میسازیم

dotnet new -n Final_SophieTravelManagment

بعدش میایم یه کلاس درست میکنیم

dotnet new classlib -n Final_SophieTravelManagment.Domain

13:34

خوب در نظر داشته باشیم که توی این چک لیسته یه سری چیزا واجب و ضروریه مثل پاسپورت

خوب ما میخوایم از بیرون کسی نتونه به این مقادیر دسترسی پیدا کنه که میایم اون رو private میکنیم ولی اینطوری درست نمیشه ، چرا ؟ چون که نمیتونیم برای id بیایم و private اش کنیم

چون یه سری مشکل برامون به وجود میاره : مشکلات :

پس چی کار کنیم که کپسوله کنیمش ؟

خوب اگر بیایم و private رو برداریم و برای این که بخوایم کاری روی این entity انجام بدیم توی conroller این کار رو انجام بدیم

ولی مشکل اینه که oop از بین میره و seperation of concerns درست که داریم ولی چون مبتنی بر oop نیست ، اشتبااااهههه اشتباه آقای کلاهدوزان میگه

خوب راه حل اینه که از یه سری obj دیگه برای کامل کردن enitity مون استفاده کنیم ، که مهمترینشون value object ها هستن

میخوایم مشکلات enitity رو در Doimian با value obj حل کنیم

کلی راه و روش دیگه هست که میتونیم ازشون استفاده کنیم

حوبvalue object خودش مثل Enitit هستش ولی به تنهایی ارزشی نداره

مثلا آدرس این رو داریم و میتونیم به هر Entity که دوست داریم بچسبونمیش ولی خودش هیج ارزشی به تنهایی نداره و نه id داره و نه کاری میشه باهاش کرد

تایم 28

خوب توی کد از یه سری تبدیل های implicit استفاده شده بود که اومدیم برای یادگیریش از deepseek کمک گرفتیم

using System;
namespace LearnImplicitOperators
 
{
    // A custom ID class that wraps an integer
    public record UserId
    {
        public int Val { get; }
        public UserId(int InputValue)
 
        {
            if (InputValue <= 0)
                throw new ArgumentException("User ID must be positive");
 
            Val = InputValue;
        }
 
         // IMPLICIT OPERATOR: UserId → int (automatic conversion)
 
         public static implicit operator int(UserId userId) => userId.Val;
        // // EXPLICIT OPERATOR: int → UserId (requires cast)
 
         public static explicit operator UserId(int SomeValue) => new(SomeValue);
        // Factory method
 
        public static UserId CreateNew() => new(new Random().Next(1, 1000));
 
    }
    
    class Program
    {
        static void Main(string[] args)
 
        {
 
            Console.WriteLine("=== LEARNING IMPLICIT OPERATORS ===\n");
            // Create a UserId
            UserId userId = UserId.CreateNew();
            Console.WriteLine($"1. Created UserId: {userId.Val}");
            // // DEMO 1: Implicit conversion (UserId → int)
 
            // Console.WriteLine("\n--- IMPLICIT CONVERSION ---");
 
             int regularInt = userId; // ← MAGIC! No cast needed!
 
             Console.WriteLine($"UserId automatically converted to int: {regularInt}");
 
            // // DEMO 2: Using in methods that expect int
 
            // Console.WriteLine("\n--- USING IN METHODS ---");
 
             DisplayUserId(userId); // Pass UserId directly to method that expects int!
 
  
 
            // // DEMO 3: Using in calculations
 
            // Console.WriteLine("\n--- USING IN CALCULATIONS ---");
 
            int nextId = userId + 1; // Can do math directly!
 
             Console.WriteLine($"Next ID would be: {nextId}");
 
  
 
            // // DEMO 4: Using in collections
 
             Console.WriteLine("\n--- USING IN COLLECTIONS ---");
 
             var userDictionary = new Dictionary<int, string>();
 
             userDictionary[userId] = "John Doe"; // Automatic conversion!
 
             Console.WriteLine($"User in dictionary: {userDictionary[userId]}");
 
  
 
            // // DEMO 5: Explicit conversion (int → UserId)
 
            // Console.WriteLine("\n--- EXPLICIT CONVERSION ---");
 
             int someNumber = 42;
 
             UserId newUserId = (UserId)someNumber; // ← Requires explicit cast
 
             Console.WriteLine($"Created UserId from int: {newUserId.Val}");
 
  
 
            // // DEMO 6: Comparison
 
            // Console.WriteLine("\n--- COMPARISON ---");
 
             bool isEqual = userId == 123; // Works due to implicit conversion
 
            // Console.WriteLine($"Is userId equal to 123? {isEqual}");
 
  
 
            // // DEMO 7: Real-world scenario
 
            // Console.WriteLine("\n--- REAL-WORLD SCENARIO ---");
 
             ProcessUserOrder(userId, "Laptop");
 
        }
 
  
 
        // Method that expects regular int
 
        static void DisplayUserId(int id)
 
        {
 
            Console.WriteLine($"Displaying user ID: {id}");
 
        }
 
  
 
        // Simulate database operation
 
        static void ProcessUserOrder(UserId userId, string product)
 
        {
 
            // Note: We can use userId directly in string interpolation
 
            // because it implicitly converts to int!
 
            Console.WriteLine($"Processing order - User: {userId}, Product: {product}");
 
            // Simulate database call that needs int
 
            SaveToDatabase(userId, product); // Automatic conversion!
 
        }
 
  
 
        static void SaveToDatabase(int userId, string product)
 
        {
 
            Console.WriteLine($"SAVED to DB - UserId: {userId}, Product: {product}");
 
        }
 
    }
 
}

نکته ای که هست اینه که وقتی که توی کلاسمون یکی پارامتر داریم اوکیه ولی وقتی که چند تا باشن نمیشه ، مگر اینه که فقط برامون مهم باشه که با اون یدونه پارامتر اصلی مثلا id بخوایم کار کنیم

کدی که خودم نوشتم برای یادگیری:

using System;
using System.Collections.Generic;
namespace Final_SophieTravelManagment.Domain.ValueObjects
{
    public record TravelerCheckListId
    {  
        public Guid Value { get; }
        public TravelerCheckListId(Guid value)
        {
            if (value == Guid.Empty)
            {
                throw new ArgumentNullException();
            }
            Value = value;
        }
       public static implicit operator TravelerCheckListId(Guid id) => new(id);
       
        public static implicit operator Guid(TravelerCheckListId id) => id.Value;
    }
 
 
    class Program
    {
        static void Main(string[] args)
        {
            // TravelerCheckListId Test = new(Guid.NewGuid());
            TravelerCheckListId Test = Guid.NewGuid();
 
            Guid MyGuid = Test;
            Console.WriteLine(Test.Value);
            //Guid GuidValue = Guid.Parse(Test.Value.ToString());
 
 
        }
    }
}

خوب این چیزی که این پایین نوشته شده برای اینه که نشون بده کامپایلر چی کار میکنه بعدش هم گفته اون تابع هایی که اون بالا ازشون استفاده شدنن اینها هستن

این مطالب بالا رو جدا کردم

این قسمت بالا رو بعدا باید جدا کنم ببرم توی قسمت csharp چون که بیسیک هستش خوب توی مثال بالا میتونیم string بگیریم و تبدیلش کنیم به person ولی دیگه age از بین میره و توی حالت بعدیش هم میتونیم person رو بگیریم و ازش اسمش رو دربیاریم ولی دیتا age اش از بین میره

خوب حالا برای این که کار قشنگ تر بشه به جای این که همینطوری بیایم و یه exception رو بفرسیتم بالا میایم یه فولدر میسازیم به اسم exception

30

این جا میاد message رو به کلاس parent پاس میده how to handle parent paramiter in child class in Csharp

خوب حالا ما هر جایی توی سیستم که ex داشته باشیم اون میاد از این کلاسه که ساختیم استفاده میکنه

خوب حالا میخوایم بیایم توی domian و ex های که اونجا اتفاق میوفته رو بنویسیم

این میاد فقط ex هایی که مرتبط با id هستش رو پیدا میکنه

میرسیم به value object ها

خوب این رو اضافه میکنیم :

تا دقیقه 46

باید از ابتدا با rider پیاده سازیش رو انجام بدم

ولی برای این قسمت آخر میخوام توضیحاتی که از deepseek گرفتم رو بنویسم که بعدا ازش استفاده کنم :

خوب حالا داستان این this چیه ، این this میاد اول با اون پارامتر های اولیه که id , name m destantion هستند میاد constructor اصلی و اولیه رو صدا میزنه و باهاش object رو میسازه اگر هم item داشته باشه میاد اون item رو هم قرار میده خوب توضیحات بیشترش رو باید بخونیم :

خوب اینجا گفته که چرا داریم از این constructor اینطوری استفاده میکنیم ؟ برای این که اگر نخوایم ازش استفاده کنیم مثل نمونه کد اولی به ازای هر چیزی که توی لیست باشه باید بریم یه بار object عه traveler check list رو بیاریم و بهش add item کنیم ولی توی حالت دوم اینطوری نیست و تمام لیست رو یکجا واردش میکنیم