پروژه پیام رسان
ASP.Net Core API
Oracle Database
Blazor SSR
SignalR
Entity Framework Core
HTML/Css

پروژه پیام رسان

این پروژه یک سیستم پیام‌رسان مدرن مبتنی بر .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 └── Keys

3. لایه Messenger.Infrastructures

این لایه مسئول تمام ارتباطات خارجی سیستم است.

هر چیزی که وابسته به تکنولوژی باشد اینجا قرار می‌گیرد.


Database

پیاده‌سازی DbContext:

public class MessengerDbContext : DbContext, IMessengerDbContext { }

Migration ها نیز در همین لایه هستند.

Migrations

JWT

پیاده‌سازی:

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 صرفاً مسئول ارائه و ارتباط با کاربر خواهد بود. این معماری برای توسعه سیستم‌های بزرگ مانند تلگرام، واتساپ، دیسکورد یا سامانه‌های چت سازمانی بسیار مناسب و مقیاس‌پذیر است.

پرسش و پاسخ

در مورد این پروژه پرسش خود را ثبت کنید. پاسخ‌ها فقط توسط مدیر ارسال می‌شوند.

0 پرسش
0 پاسخ