معماری پاک چیست: قسمت 17 – پیاده سازی لایه زیرساخت با CSV صادرات و سرویس ایمیل

Summarize this content to 400 words in Persian Lang
مقدمه:در این مقاله به ساخت آن می پردازیم لایه زیرساخت در یک پروژه دات نت، با تمرکز بر دو عملکرد کلیدی:
صادر کردن داده های رویداد به یک فایل CSV با استفاده از CsvHelper کتابخانه
ارسال اعلانهای ایمیل هنگام ایجاد رویدادهای جدید با استفاده از SendGrid خدمات
با دنبال کردن معماری پاک اصول، ما اطمینان حاصل می کنیم که برنامه از پیاده سازی زیرساخت واقعی جدا باقی می ماند. بیایید با تنظیم ساختار پروژه و ساختن لایه زیرساخت مرحله به مرحله شروع کنیم.
1. راه اندازی لایه زیرساخت
این لایه زیرساخت تعاملات سیستم خارجی مانند:
ارسال ایمیل از طریق یک سرویس ایمیل خارجی (به عنوان مثال، SendGrid).
صادرات داده ها به فایل های CSV برای گزارش یا تجزیه و تحلیل.
برای اینکه سیستم قابل نگهداری باشد، قراردادها (رابط ها) را به قسمت جدا می کنیم لایه کاربردی و پیاده سازی های واقعی را در لایه زیرساخت.
مرحله 1: لایه Infrastructure را به Solution اضافه کنید
در راه حل خود، روی نام راه حل راست کلیک کرده و انتخاب کنید افزودن > پروژه جدید.
انتخاب کنید کتابخانه کلاس پروژه را تایپ کرده و نامگذاری کنید GloboTicket.TicketManagement.Infrastructure.
2. پیاده سازی عملکرد صادرات CSV
اجازه دهید ابتدا عملکرد صادرات CSV را با استفاده از CsvHelper کتابخانه
مرحله 2.1: قرارداد صادرات CSV را در لایه برنامه تعریف کنید
در شما لایه کاربردی، پیمایش کنید به Contracts/Infrastructure.
یک رابط جدید اضافه کنید ICsvExporter.cs:
namespace GloboTicket.TicketManagement.Application.Contracts.Infrastructure
{
public interface ICsvExporter
{
byte[] ExportEventsToCsv(ListEventExportDto> eventExportDtos);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مرحله 2.2: پیاده سازی CsvExporter در لایه زیرساخت
حال، بیایید منطق صادرات واقعی را در آن پیاده سازی کنیم لایه زیرساخت.
در شما زیرساخت پروژه، پوشه ای به نام ایجاد کنید FileExport.
یک کلاس به نام اضافه کنید CsvExporter.cs:
using CsvHelper;
using System.IO;
using System.Text;
using GloboTicket.TicketManagement.Application.Contracts.Infrastructure;
using GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport;
namespace GloboTicket.TicketManagement.Infrastructure.FileExport
{
public class CsvExporter : ICsvExporter
{
public byte[] ExportEventsToCsv(ListEventExportDto> eventExportDtos)
{
using var memoryStream = new MemoryStream();
using (var streamWriter = new StreamWriter(memoryStream, Encoding.UTF8))
{
using var csvWriter = new CsvWriter(streamWriter);
csvWriter.WriteRecords(eventExportDtos); // Write event records to CSV
}
return memoryStream.ToArray(); // Return CSV as byte array
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
هدف: این کلاس لیستی از EventExportDto به فرمت CSV اشیاء می دهد و داده ها را به صورت آرایه بایتی برمی گرداند.
مرحله 2.3: ویژگی صادرات CSV را در لایه برنامه ایجاد کنید
در مرحله بعد، ما کنترل کننده ای را ایجاد می کنیم که مسئول صادرات رویدادها خواهد بود.
در لایه کاربردی، پیمایش کنید به Features/Events/Queries/GetEventsExport.
فایل های زیر را مرحله به مرحله اضافه کنید:
EventExportDto.cs:
namespace GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport
{
public class EventExportDto
{
public Guid EventId { get; set; }
public string Name { get; set; } = string.Empty;
public DateTime Date { get; set; }
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
EventExportFileVm.cs:
namespace GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport
{
public class EventExportFileVm
{
public string EventExportFileName { get; set; } = string.Empty;
public string ContentType { get; set; } = string.Empty;
public byte[]? Data { get; set; }
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
GetEventsExportQuery.cs:
using MediatR;
namespace GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport
{
public class GetEventsExportQuery : IRequestEventExportFileVm>
{
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
GetEventsExportQueryHandler.cs:
using MediatR;
using AutoMapper;
using GloboTicket.TicketManagement.Application.Contracts.Infrastructure;
using GloboTicket.TicketManagement.Domain.Entities;
namespace GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport
{
public class GetEventsExportQueryHandler : IRequestHandlerGetEventsExportQuery, EventExportFileVm>
{
private readonly IAsyncRepositoryEvent> _eventRepository;
private readonly IMapper _mapper;
private readonly ICsvExporter _csvExporter;
public GetEventsExportQueryHandler(IMapper mapper, IAsyncRepositoryEvent> eventRepository, ICsvExporter csvExporter)
{
_mapper = mapper;
_eventRepository = eventRepository;
_csvExporter = csvExporter;
}
public async TaskEventExportFileVm> Handle(GetEventsExportQuery request, CancellationToken cancellationToken)
{
var allEvents = _mapper.MapListEventExportDto>>((await _eventRepository.ListAllAsync()).OrderBy(x => x.Date));
var fileData = _csvExporter.ExportEventsToCsv(allEvents);
return new EventExportFileVm
{
ContentType = “text/csv”,
Data = fileData,
EventExportFileName = $”{Guid.NewGuid()}.csv”
};
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
3. پیاده سازی عملکرد ایمیل با استفاده از SendGrid
بعد، بیایید با استفاده از قابلیت ایمیل اضافه کنیم SendGrid.
مرحله 3.1: قرارداد خدمات ایمیل را تعریف کنید
در لایه کاربردی، پیمایش کنید به Contracts/Infrastructure.
یک رابط جدید اضافه کنید IEmailService.cs:
namespace GloboTicket.TicketManagement.Application.Contracts.Infrastructure
{
public interface IEmailService
{
Taskbool> SendEmail(Email email);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مرحله 3.2: سرویس ایمیل را در لایه زیرساخت پیاده سازی کنید
در زیرساخت پروژه، یک پوشه به نام ایجاد کنید Mail.
یک کلاس جدید به نام اضافه کنید EmailService.cs:
using GloboTicket.TicketManagement.Application.Contracts.Infrastructure;
using GloboTicket.TicketManagement.Application.Models.Mail;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;
using Microsoft.Extensions.Logging;
namespace GloboTicket.TicketManagement.Infrastructure.Mail
{
public class EmailService : IEmailService
{
private readonly EmailSettings _emailSettings;
private readonly ILoggerEmailService> _logger;
public EmailService(IOptionsEmailSettings> mailSettings, ILoggerEmailService> logger)
{
_emailSettings = mailSettings.Value;
_logger = logger;
}
public async Taskbool> SendEmail(Email email)
{
var client = new SendGridClient(_emailSettings.ApiKey);
var sendGridMessage = MailHelper.CreateSingleEmail(
new EmailAddress(_emailSettings.FromAddress, _emailSettings.FromName),
new EmailAddress(email.To),
email.Subject,
email.Body,
email.Body);
var response = await client.SendEmailAsync(sendGridMessage);
_logger.LogInformation(“Email sent”);
return response.StatusCode == System.Net.HttpStatusCode.Accepted || response.StatusCode == System.Net.HttpStatusCode.OK;
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مرحله 3.3: ارسال ایمیل از لایه برنامه
حالا بیایید از IEmailService در CreateEventCommandHandler برای ارسال ایمیل هنگام ایجاد یک رویداد.
حرکت به Features/Events/Commands/CreateEvent.
باز کنید CreateEventCommandHandler.cs و کد را به صورت زیر تغییر دهید:
using AutoMapper;
using GloboTicket.TicketManagement.Application.Contracts.Infrastructure;
using GloboTicket.TicketManagement.Application.Contracts.Persistence;
using GloboTicket.TicketManagement.Application.Models.Mail;
using GloboTicket.TicketManagement.Domain.Entities;
using MediatR;
namespace GloboTicket.TicketManagement.Application.Features.Events.Commands.CreateEvent
{
public class CreateEventCommandHandler : IRequestHandlerCreateEventCommand, Guid>
{
private readonly IEventRepository _eventRepository;
private readonly IMapper _mapper;
private readonly IEmailService _emailService;
public CreateEventCommandHandler(IMapper mapper, IEventRepository eventRepository, IEmailService emailService)
{
_mapper = mapper;
_eventRepository = eventRepository;
_emailService = emailService;
}
public async TaskGuid> Handle(CreateEventCommand request, CancellationToken cancellationToken)
{
var @event = _mapper.MapEvent>(request);
var validator = new CreateEventCommandValidator(_eventRepository);
var validationResult = await validator.ValidateAsync(request);
if (validationResult.Errors.Count > 0)
throw new Exceptions.ValidationException(validationResult);
@event = await _eventRepository.AddAsync(@event);
// Sending email notification to admin
var email = new Email
{
To = “admin@example.com”,
Subject = “A new event was created”,
Body = $”A new event was created: {request}”
};
try
{
await _email
Service.SendEmail(email);
}
catch (Exception ex)
{
// Log the error and continue
}
return @event.EventId;
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
4. ثبت خدمات در ظرف DI
برای تکمیل تنظیمات، باید ثبت نام کنید EmailService و CsvExporter در ظرف DI
در زیرساخت پروژه، حرکت به InfrastructureServiceRegistration.cs:
public static class InfrastructureServiceRegistration
{
public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration)
{
services.ConfigureEmailSettings>(configuration.GetSection(“EmailSettings”));
services.AddTransientIEmailService, EmailService>();
services.AddTransientICsvExporter, CsvExporter>();
return services;
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
حتما این روش را فراخوانی کنید Program.cs پروژه API شما:
builder.Services.AddInfrastructureServices(builder.Configuration);
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
نتیجه گیری:
در این مقاله، ما با موفقیت ایجاد کردیم لایه زیرساخت با پشتیبانی از:
صادرات CSV با استفاده از CsvHelper کتابخانه
ارسال ایمیل با استفاده از SendGrid خدمات
با پایبندی به اصول معماری پاک، اطمینان حاصل کردیم که هر دو لایه کاربردی و لایه زیرساخت جدا باقی می ماند و سیستم را قابل نگهداری و گسترش می دهد. برای کد منبع کامل، می توانید از مخزن GitHub دیدن کنید: https://github.com/mohamedtayel1980/clean-architecture
مقدمه:
در این مقاله به ساخت آن می پردازیم لایه زیرساخت در یک پروژه دات نت، با تمرکز بر دو عملکرد کلیدی:
- صادر کردن داده های رویداد به یک فایل CSV با استفاده از
CsvHelper
کتابخانه - ارسال اعلانهای ایمیل هنگام ایجاد رویدادهای جدید با استفاده از SendGrid خدمات
با دنبال کردن معماری پاک اصول، ما اطمینان حاصل می کنیم که برنامه از پیاده سازی زیرساخت واقعی جدا باقی می ماند. بیایید با تنظیم ساختار پروژه و ساختن لایه زیرساخت مرحله به مرحله شروع کنیم.
1. راه اندازی لایه زیرساخت
این لایه زیرساخت تعاملات سیستم خارجی مانند:
- ارسال ایمیل از طریق یک سرویس ایمیل خارجی (به عنوان مثال، SendGrid).
- صادرات داده ها به فایل های CSV برای گزارش یا تجزیه و تحلیل.
برای اینکه سیستم قابل نگهداری باشد، قراردادها (رابط ها) را به قسمت جدا می کنیم لایه کاربردی و پیاده سازی های واقعی را در لایه زیرساخت.
مرحله 1: لایه Infrastructure را به Solution اضافه کنید
- در راه حل خود، روی نام راه حل راست کلیک کرده و انتخاب کنید افزودن > پروژه جدید.
- انتخاب کنید کتابخانه کلاس پروژه را تایپ کرده و نامگذاری کنید
GloboTicket.TicketManagement.Infrastructure
.
2. پیاده سازی عملکرد صادرات CSV
اجازه دهید ابتدا عملکرد صادرات CSV را با استفاده از CsvHelper
کتابخانه
مرحله 2.1: قرارداد صادرات CSV را در لایه برنامه تعریف کنید
- در شما لایه کاربردی، پیمایش کنید به
Contracts/Infrastructure
. - یک رابط جدید اضافه کنید
ICsvExporter.cs
:
namespace GloboTicket.TicketManagement.Application.Contracts.Infrastructure
{
public interface ICsvExporter
{
byte[] ExportEventsToCsv(ListEventExportDto> eventExportDtos);
}
}
مرحله 2.2: پیاده سازی CsvExporter
در لایه زیرساخت
حال، بیایید منطق صادرات واقعی را در آن پیاده سازی کنیم لایه زیرساخت.
- در شما زیرساخت پروژه، پوشه ای به نام ایجاد کنید
FileExport
. - یک کلاس به نام اضافه کنید
CsvExporter.cs
:
using CsvHelper;
using System.IO;
using System.Text;
using GloboTicket.TicketManagement.Application.Contracts.Infrastructure;
using GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport;
namespace GloboTicket.TicketManagement.Infrastructure.FileExport
{
public class CsvExporter : ICsvExporter
{
public byte[] ExportEventsToCsv(ListEventExportDto> eventExportDtos)
{
using var memoryStream = new MemoryStream();
using (var streamWriter = new StreamWriter(memoryStream, Encoding.UTF8))
{
using var csvWriter = new CsvWriter(streamWriter);
csvWriter.WriteRecords(eventExportDtos); // Write event records to CSV
}
return memoryStream.ToArray(); // Return CSV as byte array
}
}
}
-
هدف: این کلاس لیستی از
EventExportDto
به فرمت CSV اشیاء می دهد و داده ها را به صورت آرایه بایتی برمی گرداند.
مرحله 2.3: ویژگی صادرات CSV را در لایه برنامه ایجاد کنید
در مرحله بعد، ما کنترل کننده ای را ایجاد می کنیم که مسئول صادرات رویدادها خواهد بود.
- در لایه کاربردی، پیمایش کنید به
Features/Events/Queries/GetEventsExport
.
- فایل های زیر را مرحله به مرحله اضافه کنید:
EventExportDto.cs
:
namespace GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport
{
public class EventExportDto
{
public Guid EventId { get; set; }
public string Name { get; set; } = string.Empty;
public DateTime Date { get; set; }
}
}
EventExportFileVm.cs
:
namespace GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport
{
public class EventExportFileVm
{
public string EventExportFileName { get; set; } = string.Empty;
public string ContentType { get; set; } = string.Empty;
public byte[]? Data { get; set; }
}
}
GetEventsExportQuery.cs
:
using MediatR;
namespace GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport
{
public class GetEventsExportQuery : IRequestEventExportFileVm>
{
}
}
GetEventsExportQueryHandler.cs
:
using MediatR;
using AutoMapper;
using GloboTicket.TicketManagement.Application.Contracts.Infrastructure;
using GloboTicket.TicketManagement.Domain.Entities;
namespace GloboTicket.TicketManagement.Application.Features.Events.Queries.GetEventsExport
{
public class GetEventsExportQueryHandler : IRequestHandlerGetEventsExportQuery, EventExportFileVm>
{
private readonly IAsyncRepositoryEvent> _eventRepository;
private readonly IMapper _mapper;
private readonly ICsvExporter _csvExporter;
public GetEventsExportQueryHandler(IMapper mapper, IAsyncRepositoryEvent> eventRepository, ICsvExporter csvExporter)
{
_mapper = mapper;
_eventRepository = eventRepository;
_csvExporter = csvExporter;
}
public async TaskEventExportFileVm> Handle(GetEventsExportQuery request, CancellationToken cancellationToken)
{
var allEvents = _mapper.MapListEventExportDto>>((await _eventRepository.ListAllAsync()).OrderBy(x => x.Date));
var fileData = _csvExporter.ExportEventsToCsv(allEvents);
return new EventExportFileVm
{
ContentType = "text/csv",
Data = fileData,
EventExportFileName = $"{Guid.NewGuid()}.csv"
};
}
}
}
3. پیاده سازی عملکرد ایمیل با استفاده از SendGrid
بعد، بیایید با استفاده از قابلیت ایمیل اضافه کنیم SendGrid.
مرحله 3.1: قرارداد خدمات ایمیل را تعریف کنید
- در لایه کاربردی، پیمایش کنید به
Contracts/Infrastructure
. - یک رابط جدید اضافه کنید
IEmailService.cs
:
namespace GloboTicket.TicketManagement.Application.Contracts.Infrastructure
{
public interface IEmailService
{
Taskbool> SendEmail(Email email);
}
}
مرحله 3.2: سرویس ایمیل را در لایه زیرساخت پیاده سازی کنید
- در زیرساخت پروژه، یک پوشه به نام ایجاد کنید
Mail
. - یک کلاس جدید به نام اضافه کنید
EmailService.cs
:
using GloboTicket.TicketManagement.Application.Contracts.Infrastructure;
using GloboTicket.TicketManagement.Application.Models.Mail;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;
using Microsoft.Extensions.Logging;
namespace GloboTicket.TicketManagement.Infrastructure.Mail
{
public class EmailService : IEmailService
{
private readonly EmailSettings _emailSettings;
private readonly ILoggerEmailService> _logger;
public EmailService(IOptionsEmailSettings> mailSettings, ILoggerEmailService> logger)
{
_emailSettings = mailSettings.Value;
_logger = logger;
}
public async Taskbool> SendEmail(Email email)
{
var client = new SendGridClient(_emailSettings.ApiKey);
var sendGridMessage = MailHelper.CreateSingleEmail(
new EmailAddress(_emailSettings.FromAddress, _emailSettings.FromName),
new EmailAddress(email.To),
email.Subject,
email.Body,
email.Body);
var response = await client.SendEmailAsync(sendGridMessage);
_logger.LogInformation("Email sent");
return response.StatusCode == System.Net.HttpStatusCode.Accepted || response.StatusCode == System.Net.HttpStatusCode.OK;
}
}
}
مرحله 3.3: ارسال ایمیل از لایه برنامه
حالا بیایید از IEmailService
در CreateEventCommandHandler
برای ارسال ایمیل هنگام ایجاد یک رویداد.
- حرکت به
Features/Events/Commands/CreateEvent
. - باز کنید
CreateEventCommandHandler.cs
و کد را به صورت زیر تغییر دهید:
using AutoMapper;
using GloboTicket.TicketManagement.Application.Contracts.Infrastructure;
using GloboTicket.TicketManagement.Application.Contracts.Persistence;
using GloboTicket.TicketManagement.Application.Models.Mail;
using GloboTicket.TicketManagement.Domain.Entities;
using MediatR;
namespace GloboTicket.TicketManagement.Application.Features.Events.Commands.CreateEvent
{
public class CreateEventCommandHandler : IRequestHandlerCreateEventCommand, Guid>
{
private readonly IEventRepository _eventRepository;
private readonly IMapper _mapper;
private readonly IEmailService _emailService;
public CreateEventCommandHandler(IMapper mapper, IEventRepository eventRepository, IEmailService emailService)
{
_mapper = mapper;
_eventRepository = eventRepository;
_emailService = emailService;
}
public async TaskGuid> Handle(CreateEventCommand request, CancellationToken cancellationToken)
{
var @event = _mapper.MapEvent>(request);
var validator = new CreateEventCommandValidator(_eventRepository);
var validationResult = await validator.ValidateAsync(request);
if (validationResult.Errors.Count > 0)
throw new Exceptions.ValidationException(validationResult);
@event = await _eventRepository.AddAsync(@event);
// Sending email notification to admin
var email = new Email
{
To = "admin@example.com",
Subject = "A new event was created",
Body = $"A new event was created: {request}"
};
try
{
await _email
Service.SendEmail(email);
}
catch (Exception ex)
{
// Log the error and continue
}
return @event.EventId;
}
}
}
4. ثبت خدمات در ظرف DI
برای تکمیل تنظیمات، باید ثبت نام کنید EmailService
و CsvExporter
در ظرف DI
- در زیرساخت پروژه، حرکت به
InfrastructureServiceRegistration.cs
:
public static class InfrastructureServiceRegistration
{
public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration)
{
services.ConfigureEmailSettings>(configuration.GetSection("EmailSettings"));
services.AddTransientIEmailService, EmailService>();
services.AddTransientICsvExporter, CsvExporter>();
return services;
}
}
- حتما این روش را فراخوانی کنید
Program.cs
پروژه API شما:
builder.Services.AddInfrastructureServices(builder.Configuration);
نتیجه گیری:
در این مقاله، ما با موفقیت ایجاد کردیم لایه زیرساخت با پشتیبانی از:
-
صادرات CSV با استفاده از
CsvHelper
کتابخانه - ارسال ایمیل با استفاده از SendGrid خدمات
با پایبندی به اصول معماری پاک، اطمینان حاصل کردیم که هر دو لایه کاربردی و لایه زیرساخت جدا باقی می ماند و سیستم را قابل نگهداری و گسترش می دهد.
برای کد منبع کامل، می توانید از مخزن GitHub دیدن کنید: https://github.com/mohamedtayel1980/clean-architecture