
پروژه پیام رسان
این پروژه یک سیستم پیامرسان مدرن مبتنی بر .NET است که با استفاده از معماری لایهای و جداسازی مسئولیتها طراحی شده است. لایه Domain شامل موجودیتها و قوانین کسبوکار، لایه ApplicationService شامل سرویسهای کاربردی، قراردادها و Use Caseها، لایه Infrastructure مسئول پیادهسازی زیرساختهایی مانند پایگاه داده، ذخیرهسازی فایل و احراز هویت JWT، و لایه UI مبتنی بر Blazor SSR برای ارائه رابط کاربری و مدیریت درخواستها است.
ویدیوی معرفی
گالری تصاویر
1 تصویرنمای داشبورد
در این قسمت نمای داشبورد رو میتونین ببینین
نمای داشبورد
در این قسمت نمای داشبورد رو میتونین ببینین
توضیحات کامل
این پروژه یک سیستم پیامرسان (Messenger) مبتنی بر .NET است که با استفاده از Domain-Driven Design (DDD)، Clean Architecture و تفکیک لایهها طراحی شده است. هدف اصلی این ساختار آن است که منطق کسبوکار، زیرساخت، رابط کاربری و سرویسهای کاربردی کاملاً از یکدیگر مستقل باشند تا سیستم در آینده بهراحتی توسعه، تست و نگهداری شود.
1. لایه Messenger.Domain
این لایه قلب سیستم است و مهمترین بخش پروژه محسوب میشود.
وظایف این لایه:
موجودیتها (Entities)
Aggregate Root ها
Value Object ها
Enum ها
قوانین و منطق دامنه (Business Rules)
نمونه:
public class Conversation : AggregateRoot<long> { public string Title { get; private set; } private readonly List<Message> _messages = new(); public IReadOnlyCollection<Message> Messages => _messages; public void SendMessage(long senderId,string text) { _messages.Add(new Message(senderId,text)); } }در این لایه هیچ وابستگی به موارد زیر وجود ندارد:
❌ Entity Framework
❌ SignalR
❌ JWT
❌ DTO
❌ File Storage
❌ Localization
❌ HTTP
هدف:
اگر فردا بخواهی SQL Server را به Oracle تغییر دهی، این لایه نباید حتی یک خط تغییر کند.
2. لایه Messenger.ApplicationService
این لایه Use Case های سیستم را پیادهسازی میکند.
در واقع اینجا مشخص میشود که سیستم چه کارهایی میتواند انجام دهد.
مثال:
ارسال پیام
حذف پیام
ایجاد گروه
خروج از گروه
دریافت لیست گفتگوها
تغییر پروفایل
نمونه:
public class SendMessageCommand { public long ConversationId { get; set; } public string Text { get; set; } }public class SendMessageHandler { public async Task Handle( SendMessageCommand command) { ... } }Contracts
تمام DTO ها به این لایه منتقل شدهاند.
مثال:
Messenger.ApplicationService └── Contracts ├── SendMessageRequest ├── SendMessageResponse ├── LoginRequest └── LoginResponseقبلاً این DTO ها در Domain بودند که از نظر معماری صحیح نبود.
Persistence Abstractions
به جای وابستگی مستقیم به DbContext:
MessengerDbContextیک Abstraction تعریف شده:
public interface IMessengerDbContext { DbSet<User> Users { get; } DbSet<Message> Messages { get; } Task<int> SaveChangesAsync( CancellationToken cancellationToken); }سرویسهای Application فقط این Interface را میبینند.
Localization
متنهای چندزبانه و Resource ها نیز از Domain خارج شدهاند.
مثال:
Messenger.ApplicationService └── Localization ├── Resources └── Keys3. لایه Messenger.Infrastructures
این لایه مسئول تمام ارتباطات خارجی سیستم است.
هر چیزی که وابسته به تکنولوژی باشد اینجا قرار میگیرد.
Database
پیادهسازی DbContext:
public class MessengerDbContext : DbContext, IMessengerDbContext { }Migration ها نیز در همین لایه هستند.
MigrationsJWT
پیادهسازی:
public class JwtTokenService : IJwtTokenService { }وظیفه:
تولید Access Token
تولید Refresh Token
اعتبارسنجی Token
File Storage
پیادهسازی:
public class FileService : IFileService { }برای:
آپلود تصویر
ذخیره فایل
حذف فایل
Dependency Injection
ثبت سرویسهای زیرساختی:
services.AddInfrastructure();4. لایه Messenger.UI
این لایه Presentation Layer است.
در پروژه شما:
Blazor SSRاستفاده شده است.
وظایف UI
صفحات Blazor
Components
Controllers
Middleware
Authentication Pipeline
SignalR Endpoints
نمونه:
app.MapHub<ChatHub>("/chat");Program.cs
قبلاً همه چیز داخل Program.cs ثبت میشد.
مثلاً:
builder.Services.AddDbContext(); builder.Services.AddScoped<FileService>(); builder.Services.AddScoped<JwtTokenService>();اکنون ساده شده:
builder.Services.AddApplication(); builder.Services.AddInfrastructure();و هر لایه مسئول ثبت سرویسهای خودش است.
Dependency Direction
وابستگیها به این شکل هستند:
UI ↓ ApplicationService ↓ Domain Infrastructure ↓ ApplicationService ↓ Domainو نه:
Domain ↓ Infrastructureچنین وابستگیای نباید وجود داشته باشد.
Refactoring انجام شده
طبق توضیحاتی که ارائه کردی، موارد زیر اصلاح شدهاند:
DTO ها
از:
Domain/DTOsبه:
ApplicationService/Contractsمنتقل شدهاند.
Localization
از Domain خارج شده و به Application منتقل شده است.
DbContext
Application دیگر مستقیم به:
MessengerDbContextوابسته نیست.
بلکه به:
IMessengerDbContextوابسته است.
JwtTokenService
از Application خارج شده و به Infrastructure منتقل شده است.
FileService
از Application خارج شده و به Infrastructure منتقل شده است.
Dependency Injection
برای هر لایه Extension جداگانه ایجاد شده:
AddApplication() AddInfrastructure()مشکل باقیمانده
در حال حاضر SignalR Hub ها هنوز در ApplicationService قرار دارند.
مثلاً:
ChatHubاین موضوع باعث شده:
ApplicationService ↓ SignalRوابستگی ایجاد شود.
در حالی که SignalR یک تکنولوژی است و باید در UI قرار بگیرد.
راهکار پیشنهادی
تعریف Abstraction در Application:
public interface IRealtimeNotifier { Task NotifyUser( long userId, string message); }Application فقط این Interface را میشناسد.
پیادهسازی در UI:
public class SignalRNotifier : IRealtimeNotifier { }و Hub:
public class ChatHub : Hub { }به UI منتقل میشود.
نتیجه نهایی
بعد از انتقال Hub ها، معماری پروژه تقریباً به یک پیادهسازی استاندارد Clean Architecture + DDD + CQRS برای یک پیامرسان Real-Time تبدیل میشود. در این ساختار، Domain کاملاً مستقل از تکنولوژیها باقی میماند، Application فقط Use Caseها را مدیریت میکند، Infrastructure جزئیات فنی را پیادهسازی میکند و UI صرفاً مسئول ارائه و ارتباط با کاربر خواهد بود. این معماری برای توسعه سیستمهای بزرگ مانند تلگرام، واتساپ، دیسکورد یا سامانههای چت سازمانی بسیار مناسب و مقیاسپذیر است.
پرسش و پاسخ
در مورد این پروژه پرسش خود را ثبت کنید. پاسخها فقط توسط مدیر ارسال میشوند.