I want you to act as a Senior C# software developer. with lots of experience in C# Domain Driven Design, using C# Clean Architecture. I will provide some with the Invoice Entity, then I will tell you to explain the code, you can see that class uses Clean Architecture C# design patterns under domain-driven design, can you explain the C# design patterns used considering that in another part of the application (i will not provide you with those extra classes but just know they exist and are there to be used by the entity class), those classes are the Invoice specification class, get One Invoice by Id with related children entities specification class, the fluent epi configuration class for the Invoice, the DTO for the Invoice, the auto mapper profile for the profile, the endpoints for the invoice update endpoint class, the create invoice as well as the get List of invoices and the get one complete invoice with related parent entities and children entities GetOneWithChildrenEntities endpoint, I also have the blazor web assembly Invoice UI and the code to communicate with the endpoint.
so as you can see I have a complete app, please explain the C# design patterns used, here is the entity invoice class

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Ardalis.GuardClauses;
using dddSimpleInvoice.Core.Events;
using dddSimpleInvoiceL.SharedKernel;
using dddSimpleInvoiceL.SharedKernel.Interfaces;

namespace dddSimpleInvoice.Core.Entities
{

 public class Invoice : BaseEntityEv, IAggregateRoot
 {
 [Key]
 public Guid InvoiceId { get; private set; }

 public string DeliveryAddressId { get; private set; }

 public string InvoiceCode { get; private set; }

 public DateTime InvoiceDate { get; private set; }

 public string? CustomerPurchaseOrderNumber { get; private set; }

 public bool IsCreditNote { get; private set; }

 public string? CreditNoteReason { get; private set; }

 public string? Comments { get; private set; }

 public string? DeliveryInstructions { get; private set; }

 public string? InternalComments { get; private set; }

 public Guid LastEditedBy { get; private set; }

 public DateTime LastEditedWhen { get; private set; }

 public DateTime CreateDate { get; private set; }

 public DateTime? DueDate { get; private set; }

 public DateTime? ShipDate { get; private set; }

 public DateTime? DateInvoiced { get; private set; }

 public int InvoiceStatus { get; private set; }

 public decimal? TotalSale { get; private set; }

 public decimal? TotalSaleTax { get; private set; }

 public void SetDeliveryAddressId(string deliveryAddressId)
 {
 DeliveryAddressId = deliveryAddressId;
 }
 public void SetInvoiceCode(string invoiceCode)
 {
 InvoiceCode = Guard.Against.NullOrEmpty(invoiceCode, nameof(invoiceCode));
 }

 public void UpdateCustomerForInvoice(Guid newCustomerId)
 {
 Guard.Against.NullOrEmpty(newCustomerId, nameof(newCustomerId));
 if (newCustomerId == CustomerId)
 {
 return;
 }

 CustomerId = newCustomerId;
 }

 public void SetCustomerPurchaseOrderNumber(string customerPurchaseOrderNumber)
 {
 CustomerPurchaseOrderNumber = customerPurchaseOrderNumber;
 }
 public void SetCreditNoteReason(string creditNoteReason)
 {
 CreditNoteReason = creditNoteReason;
 }
 public void SetComments(string comments)
 {
 Comments = comments;
 }
 public void SetDeliveryInstructions(string deliveryInstructions)
 {
 DeliveryInstructions = deliveryInstructions;
 }
 public void SetInternalComments(string internalComments)
 {
 InternalComments = internalComments;
 }
 public virtual Customer Customer { get; private set; }

 public Guid CustomerId { get; private set; }

 private readonly List \_invoiceDetails = new();

 public IEnumerable InvoiceDetails => \_invoiceDetails.AsReadOnly();
 public void AddNewInvoiceDetail(InvoiceDetail invoiceDetail)
 {
 Guard.Against.Null(invoiceDetail, nameof(invoiceDetail));
 Guard.Against.NullOrEmpty(invoiceDetail.InvoiceDetailId, nameof(invoiceDetail.InvoiceDetailId));
 Guard.Against.DuplicateInvoiceDetail(\_invoiceDetails, invoiceDetail, nameof(invoiceDetail));
 \_invoiceDetails.Add(invoiceDetail);
 }

 public void DeleteInvoiceDetail(InvoiceDetail invoiceDetail)
 {
 Guard.Against.Null(invoiceDetail, nameof(invoiceDetail));
 var invoiceDetailToDelete = \_invoiceDetails
 .Where(id => id.InvoiceDetailId == invoiceDetail.InvoiceDetailId)
 .FirstOrDefault();
 if (invoiceDetailToDelete != null)
 {
 \_invoiceDetails.Remove(invoiceDetailToDelete);
 }
 }

 private Invoice() {} // EF required

 [SetsRequiredMembers]
 public Invoice(Guid invoiceId, Guid customerId, string? deliveryAddressId, string invoiceCode, DateTime invoiceDate, string? customerPurchaseOrderNumber, bool isCreditNote, string? creditNoteReason, string? comments, string? deliveryInstructions, string? internalComments, System.Guid lastEditedBy, DateTime lastEditedWhen, DateTime createDate, DateTime? dueDate, DateTime? shipDate, DateTime? dateInvoiced, int invoiceStatus, decimal? totalSale, decimal? totalSaleTax)
 {
 InvoiceId = Guard.Against.NullOrEmpty(invoiceId, nameof(invoiceId));
 CustomerId = Guard.Against.NullOrEmpty(customerId, nameof(customerId));
 DeliveryAddressId = deliveryAddressId;
 InvoiceCode = Guard.Against.NullOrWhiteSpace(invoiceCode, nameof(invoiceCode));
 InvoiceDate = Guard.Against.OutOfSQLDateRange(invoiceDate, nameof(invoiceDate));
 CustomerPurchaseOrderNumber = customerPurchaseOrderNumber;
 IsCreditNote = Guard.Against.Null(isCreditNote, nameof(isCreditNote));
 CreditNoteReason = creditNoteReason;
 Comments = comments;
 DeliveryInstructions = deliveryInstructions;
 InternalComments = internalComments;
 LastEditedBy = Guard.Against.NullOrEmpty(lastEditedBy, nameof(lastEditedBy));
 LastEditedWhen = Guard.Against.OutOfSQLDateRange(lastEditedWhen, nameof(lastEditedWhen));
 CreateDate = Guard.Against.OutOfSQLDateRange(createDate, nameof(createDate));
 DueDate = dueDate;
 ShipDate = shipDate;
 DateInvoiced = dateInvoiced;
 InvoiceStatus = Guard.Against.NegativeOrZero(invoiceStatus, nameof(invoiceStatus));
 TotalSale = totalSale;
 TotalSaleTax = totalSaleTax;

 }

 }
}
C# 클린 아키텍처를 사용하여 C# 도메인 중심 디자인에 대한 많은 경험을 가진 선임 C# 소프트웨어 개발자로 활동하기를 원합니다. 나는 송장 엔티티를 제공 한 다음 코드를 설명하라고 말할 것입니다, 그 클래스는 도메인 중심 디자인에서 클린 아키텍처 C # 디자인 패턴을 사용하는 것을 볼 수 있습니다, 응용 프로그램의 다른 부분에서 (나는 당신에게 그 추가 클래스를 제공하지 않고 단지 그들이 존재하고 엔티티 클래스에서 사용하기 위해 거기에 있다는 것을 알고), 그 클래스는 송장 사양 클래스임을 고려하여 사용 된 C # 디자인 패턴을 설명 할 수 있습니다, 관련 하위 엔티티 사양 클래스가있는 ID 별 송장 가져 오기, 송장에 대한 유창한 에피 구성 클래스, 송장에 대한 DTO, 프로필에 대한 자동 매퍼 프로필, 송장 업데이트 엔드 포인트 클래스의 엔드 포인트, 송장 생성 및 송장 목록 가져 오기, 관련 부모 엔티티 및 하위 엔티티가있는 하나의 완전한 송장 가져 오기 GetOneWithChildrenEntities 엔드 포인트, 블레이저 웹 어셈블리 송장 UI 및 엔드 포인트와 통신하는 코드도 있습니다.보시다시피 앱이 완성되었으므로 사용된 C# 디자인 패턴을 설명하면 다음과 같습니다. 엔티티 인보이스 클래스using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.Diagnostics.CodeAnalysis;using System.Linq;using Ardalis.GuardClauses;using dddSimpleInvoice.Core.Events;사용 dddSimpleInvoiceL.SharedKernel;사용 dddSimpleInvoiceL.SharedKernel.Interfaces;네임스페이스 dddSimpleInvoice.Core.Entities{ public class Invoice : BaseEntityEv, IAggregateRoot { [Key] public Guid InvoiceId { get; private set; } public string DeliveryAddressId { get; private set; } public string InvoiceCode { get; private set; } public DateTime InvoiceDate { get; private set; } 공개 문자열? CustomerPurchaseOrderNumber { get; private set; } public bool IsCreditNote { get; private set; } 공개 문자열? CreditNoteReason { get; private set; } 공개 문자열? Comments { get; private set; } 공개 문자열? DeliveryInstructions { get; private set; } 공개 문자열? InternalComments { get; private set; } public Guid LastEditedBy { get; private set; } public DateTime LastEditedWhen { get; private set; } public DateTime CreateDate { get; private set; } public DateTime? DueDate { get; private set; } public DateTime? ShipDate { get; private set; } public DateTime? DateInvoiced { get; private set; } public int InvoiceStatus { get; private set; } public decimal? TotalSale { get; private set; } public decimal? TotalSaleTax { get; private set; } public void SetDeliveryAddressId(문자열 deliveryAddressId) { 배달주소번호 = 배달주소번호; } public void SetInvoiceCode(문자열 invoiceCode) { InvoiceCode = Guard.Against.NullOrEmpty(invoiceCode, nameof(invoiceCode)); } public void UpdateCustomerForInvoice(Guid newCustomerId) { Guard.Against.NullOrEmpty(newCustomerId, nameof(newCustomerId)); if (newCustomerId == CustomerId) { return; } CustomerId = newCustomerId; } public void SetCustomerPurchaseOrderNumber(문자열 customerPurchaseOrderNumber) { 고객구매주문번호 = 고객구매주문번호; } public void SetCreditNoteReason(string creditNoteReason) { CreditNoteReason = creditNoteReason; } public void SetComments(문자열 코멘트) { Comments = 코멘트; } public void SetDeliveryInstructions(문자열 deliveryInstructions) { 배달 지침 = 배달 지침; } public void SetInternalComments(문자열 internalComments) { InternalComments = 내부 코멘트; } public virtual Customer Customer { get; private set; } public Guid CustomerId { get; private set; } 비공개 읽기 전용 목록 \_invoiceDetails = new(); public IEnumerable InvoiceDetails => \_invoiceDetails.AsReadOnly(); public void AddNewInvoiceDetail(InvoiceDetail invoiceDetail) { Guard.Against.Null(invoiceDetail, nameof(invoiceDetail)); Guard.Against.NullOrEmpty(invoiceDetail.InvoiceDetailId, nameof(invoiceDetail.InvoiceDetailId)); Guard.Against.DuplicateInvoiceDetail(\_invoiceDetails, invoiceDetail, nameof(invoiceDetail)); \_invoiceDetails.Add(invoiceDetail); } public void DeleteInvoiceDetail(InvoiceDetail invoiceDetail) { Guard.Against.Null(invoiceDetail, nameof(invoiceDetail)); var invoiceDetailToDelete = \_invoiceDetails .Where(id => id.InvoiceDetailId == invoiceDetail.InvoiceDetailId) .FirstOrDefault(); if (invoiceDetailToDelete != null) { \_invoiceDetails.Remove(invoiceDetailToDelete); } } private Invoice() {} // EF 필수 [SetsRequiredMembers] public Invoice(Guid invoiceId, Guid customerId, string? deliveryAddressId, string invoiceCode, DateTime invoiceDate, string? customerPurchaseOrderNumber, bool isCreditNote, string? creditNoteReason, string? comments, string? deliveryInstructions, string? internalComments, System.Guid lastEditedBy, DateTime lastEditedWhen, DateTime createDate, DateTime? dueDate, DateTime? shipDate, DateTime)