Deva.Extensions.Gateway 1.0.0

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package Deva.Extensions.Gateway --version 1.0.0
                    
NuGet\Install-Package Deva.Extensions.Gateway -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Deva.Extensions.Gateway" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Deva.Extensions.Gateway" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Deva.Extensions.Gateway" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Deva.Extensions.Gateway --version 1.0.0
                    
#r "nuget: Deva.Extensions.Gateway, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Deva.Extensions.Gateway@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Deva.Extensions.Gateway&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Deva.Extensions.Gateway&version=1.0.0
                    
Install as a Cake Tool

Deva Gateway Extensions

.NET 8 kütüphanesi ile email ve SMS gönderme işlemlerini çeşitli gateway sağlayıcıları üzerinden gerçekleştirin.

.NET 8 License: MIT

📋 İçindekiler

✨ Özellikler

  • 🔌 Multiple Adapters: Mailjet, Türk Telekom, NetGSM desteği
  • 📧 Email Service: HTML/Text email gönderme, çoklu attachment desteği
  • 📱 SMS Service: Türk Telekom ve NetGSM üzerinden SMS gönderme
  • ⚡ Async/Await: Modern asenkron programlama desteği
  • 🛡️ Type Safety: Güçlü tip güvenliği ve validation
  • 📁 Flexible Attachments: Dosya yolu, Base64, Stream, Byte array desteği
  • 🏗️ DI Integration: .NET Dependency Injection entegrasyonu
  • 📊 Response Tracking: Detaylı HTTP response bilgileri
  • 🔍 Error Handling: Kapsamlı hata yönetimi ve logging

🚀 Kurulum

NuGet Package Manager

Install-Package Deva.Extensions.Gateway

.NET CLI

dotnet add package Deva.Extensions.Gateway

Package Reference

<PackageReference Include="Deva.Extensions.Gateway" Version="1.0.0" />

⚙️ Yapılandırma

1. Dependency Injection Setup

Program.cs dosyanızda servisi kaydedin:

using Deva.Extensions.G2way.Infrastructures.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Deva Gateway servisini ekleyin
builder.Services.AddDevaGateway(builder.Configuration);

var app = builder.Build();

2. Configuration Setup

appsettings.json dosyanızda gateway ayarlarını yapılandırın:

{
  "DevaGateway": {
    "ApiUrl": "https://your-domain.com",
    "AppName": "MyApplication",
    "AppVersion": "1.0.0",
    "Adapters": [
      {
        "Adapter": 1,
        "PublicKey": "your-mailjet-public-key",
        "SecretKey": "your-mailjet-secret-key"
      },
      {
        "Adapter": 2,
        "PublicKey": "your-turktelekom-public-key",
        "SecretKey": "your-turktelekom-secret-key"
      },
      {
        "Adapter": 3,
        "PublicKey": "your-netgsm-public-key",
        "SecretKey": "your-netgsm-secret-key"
      }
    ]
  }
}

Adapter Türleri

Adapter Değer Hizmet Açıklama
Mailjet 1 Email Email gönderme servisi
Turktelekom 2 SMS Türk Telekom SMS servisi
Netgsm 3 SMS NetGSM SMS servisi

Zorunlu Konfigürasyon Alanları

Tüm aşağıdaki alanlar zorunludur ve validation ile kontrol edilir:

{
  "DevaGateway": {
    "ApiUrl": "https://...",        // ✅ Zorunlu - Geçerli URL formatında
    "AppName": "MyApp",             // ✅ Zorunlu - 1-100 karakter
    "AppVersion": "1.0.0",          // ✅ Zorunlu
    "Adapters": [                   // ✅ Zorunlu - En az 1 adapter
      {
        "Adapter": 1,               // ✅ Zorunlu - Geçerli enum değeri
        "PublicKey": "pub_...",     // ✅ Zorunlu - 1-500 karakter
        "SecretKey": "sec_..."      // ✅ Zorunlu - 1-500 karakter
      }
    ]
  }
}

💻 Kullanım

Email Gönderme

Temel Email Gönderme
public class EmailService
{
    private readonly IDevaGatewayService _gatewayService;

    public EmailService(IDevaGatewayService gatewayService)
    {
        _gatewayService = gatewayService;
    }

    public async Task<bool> SendEmailAsync()
    {
        var emailModel = new SendMailGatewayModel
        {
            To = new[] { "recipient@example.com" },
            Subject = "Test Email",
            Text = "Bu bir test emailidir.",
            Html = "<h1>Test Email</h1><p>Bu bir test emailidir.</p>",
            ReturnException = false // Hata durumunda exception fırlatma
        };

        var result = await _gatewayService.SendMailAsync(emailModel);
        return result?.HttpResponse?.IsSuccess ?? false;
    }
}
CC ve BCC ile Email Gönderme
var emailModel = new SendMailGatewayModel
{
    To = new[] { "primary@example.com" },
    Cc = new[] { "cc1@example.com", "cc2@example.com" },
    Bcc = new[] { "bcc@example.com" },
    Subject = "CC/BCC Test",
    Html = "<p>CC ve BCC ile test emaili</p>",
    ReturnException = false
};

var result = await _gatewayService.SendMailAsync(emailModel);

SMS Gönderme

public async Task<bool> SendSmsAsync()
{
    var smsModel = new SendSmsGatewayModel
    {
        To = "5551234567",
        Message = "Test SMS mesajı",
        ReturnException = false
    };

    var result = await _gatewayService.SendSmsAsync(smsModel);
    return result?.HttpResponse?.IsSuccess ?? false;
}

Attachment Ekleme

Email'lere çeşitli yöntemlerle attachment ekleyebilirsiniz:

1. Dosya Yolu ile Attachment
var emailModel = new SendMailGatewayModel
{
    To = new[] { "recipient@example.com" },
    Subject = "Ek Dosyalı Email",
    Html = "<p>Bu emailde ek dosya bulunmaktadır.</p>",
    Attachments = new SendMailGatewayModelAttachments
    {
        ShowFileExceptions = true, // Dosya hatalarını göster
        Files = new[]
        {
            new SendMailGatewayModelAttachment
            {
                FilePath = @"C:\Documents\report.pdf"
            },
            new SendMailGatewayModelAttachment
            {
                FilePath = @"C:\Images\chart.png"
            }
        }
    },
    ReturnException = false
};
2. Base64 String ile Attachment
var base64Content = Convert.ToBase64String(File.ReadAllBytes(@"C:\file.pdf"));

var emailModel = new SendMailGatewayModel
{
    To = new[] { "recipient@example.com" },
    Subject = "Base64 Attachment",
    Html = "<p>Base64 attachment örneği</p>",
    Attachments = new SendMailGatewayModelAttachments
    {
        Files = new[]
        {
            new SendMailGatewayModelAttachment
            {
                Base64Model = new SendMailGatewayModelAttachmentBase64
                {
                    FileName = "document.pdf",
                    Base64 = base64Content
                }
            }
        }
    },
    ReturnException = false
};
3. Stream ile Attachment
using var fileStream = new FileStream(@"C:\file.pdf", FileMode.Open, FileAccess.Read);

var emailModel = new SendMailGatewayModel
{
    To = new[] { "recipient@example.com" },
    Subject = "Stream Attachment",
    Html = "<p>Stream attachment örneği</p>",
    Attachments = new SendMailGatewayModelAttachments
    {
        Files = new[]
        {
            new SendMailGatewayModelAttachment
            {
                StreamModel = new SendMailGatewayModelAttachmentStream
                {
                    FileName = "document.pdf",
                    Stream = fileStream
                }
            }
        }
    },
    ReturnException = false
};
4. Byte Array ile Attachment
var fileBytes = File.ReadAllBytes(@"C:\file.pdf");

var emailModel = new SendMailGatewayModel
{
    To = new[] { "recipient@example.com" },
    Subject = "Byte Array Attachment",
    Html = "<p>Byte array attachment örneği</p>",
    Attachments = new SendMailGatewayModelAttachments
    {
        Files = new[]
        {
            new SendMailGatewayModelAttachment
            {
                BytesModel = new SendMailGatewayModelAttachmentBytes
                {
                    FileName = "document.pdf",
                    Buffer = fileBytes
                }
            }
        }
    },
    ReturnException = false
};
5. Çoklu Attachment Türleri (Karışık Kullanım)
var emailModel = new SendMailGatewayModel
{
    To = new[] { "recipient@example.com" },
    Subject = "Çoklu Attachment Test",
    Html = "<p>Farklı türde attachment'lar</p>",
    Attachments = new SendMailGatewayModelAttachments
    {
        ShowFileExceptions = false, // Hatalı dosyaları atla
        Files = new[]
        {
            // Dosya yolu
            new SendMailGatewayModelAttachment
            {
                FilePath = @"C:\report.pdf"
            },
            // Base64
            new SendMailGatewayModelAttachment
            {
                Base64Model = new SendMailGatewayModelAttachmentBase64
                {
                    FileName = "data.json",
                    Base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes("{\"test\": true}"))
                }
            },
            // Byte array
            new SendMailGatewayModelAttachment
            {
                BytesModel = new SendMailGatewayModelAttachmentBytes
                {
                    FileName = "info.txt",
                    Buffer = Encoding.UTF8.GetBytes("Önemli bilgiler...")
                }
            }
        }
    },
    ReturnException = false
};

📊 Response Yapısı

Email Response (SendMailGatewayDto)

public class SendMailGatewayDto
{
    public HttpResponseDto HttpResponse { get; set; }
    public string MessageId { get; set; } // Gateway'den dönen mesaj ID'si
    public bool IsSuccess { get; set; }
    public string ErrorMessage { get; set; }
}

SMS Response (SendSmsGatewayDto)

public class SendSmsGatewayDto
{
    public HttpResponseDto HttpResponse { get; set; }
    public string MessageId { get; set; } // Gateway'den dönen mesaj ID'si
    public bool IsSuccess { get; set; }
    public string ErrorMessage { get; set; }
}

HTTP Response (HttpResponseDto)

public class HttpResponseDto
{
    public int StatusCode { get; set; }        // HTTP status kodu
    public bool IsSuccess { get; set; }        // 200 ise true
    public string ExceptionMessage { get; set; } // Hata mesajı
}

HTTP Status Kodları

Status Code Durum Açıklama
200 ✅ Success İşlem başarılı
400 ❌ Bad Request Geçersiz parametre
401 ❌ Unauthorized Geçersiz API anahtarları
403 ❌ Forbidden Yetkisiz erişim
429 ⚠️ Rate Limit Çok fazla istek
500 ❌ Server Error Sunucu hatası
-1 ❌ Network Error Bağlantı hatası
-2 ❌ Exception Uygulama hatası

Response Örnek Kullanım

var result = await _gatewayService.SendMailAsync(emailModel);

// Status code kontrolü
switch (result?.HttpResponse?.StatusCode)
{
    case 200:
        Console.WriteLine($"✅ Email başarıyla gönderildi! Message ID: {result.MessageId}");
        break;
    case 401:
        Console.WriteLine("❌ API anahtarları geçersiz!");
        break;
    case 429:
        Console.WriteLine("⚠️ Rate limit aşıldı, lütfen bekleyin.");
        break;
    case -1:
        Console.WriteLine("❌ Network hatası occurred.");
        break;
    default:
        Console.WriteLine($"❌ Hata: {result?.HttpResponse?.ExceptionMessage}");
        break;
}

🛠️ Error Handling

Exception Türleri

// Gateway genel hataları
public class BaseGatewayException : Exception

// Attachment dosya bulunamadı
public class NotFoundAttachmentFileException : Exception

Error Handling Stratejileri

1. Exception Fırlatma (ReturnException = false)
try
{
    var emailModel = new SendMailGatewayModel
    {
        To = new[] { "test@example.com" },
        Subject = "Test",
        Text = "Test message",
        ReturnException = false // Exception fırlat
    };

    var result = await _gatewayService.SendMailAsync(emailModel);
    
    if (result?.HttpResponse?.IsSuccess == true)
    {
        Console.WriteLine("Email başarıyla gönderildi!");
    }
}
catch (BaseGatewayException ex)
{
    Console.WriteLine($"Gateway hatası: {ex.Message}");
}
catch (NotFoundAttachmentFileException ex)
{
    Console.WriteLine($"Attachment hatası: {ex.Message}");
}
catch (ArgumentNullException ex)
{
    Console.WriteLine($"Konfigürasyon hatası: {ex.Message}");
}
2. Error Response Döndürme (ReturnException = true)
var emailModel = new SendMailGatewayModel
{
    To = new[] { "test@example.com" },
    Subject = "Test",
    Text = "Test message",
    ReturnException = true // Exception fırlatma, response döndür
};

var result = await _gatewayService.SendMailAsync(emailModel);

if (result?.HttpResponse?.IsSuccess == true)
{
    Console.WriteLine("Email başarıyla gönderildi!");
}
else
{
    Console.WriteLine($"Email gönderimi başarısız: {result?.HttpResponse?.ExceptionMessage}");
    Console.WriteLine($"Status Code: {result?.HttpResponse?.StatusCode}");
}

Attachment Error Handling

var emailModel = new SendMailGatewayModel
{
    Attachments = new SendMailGatewayModelAttachments
    {
        ShowFileExceptions = true, // Dosya hatalarında exception fırlat
        Files = new[]
        {
            new SendMailGatewayModelAttachment
            {
                FilePath = @"C:\nonexistent\file.pdf" // Olmayan dosya
            }
        }
    }
};

// ShowFileExceptions = true ise NotFoundAttachmentFileException fırlatır
// ShowFileExceptions = false ise dosya atlanır ve email gönderilir

Comprehensive Error Handler

public class EmailErrorHandler
{
    public async Task<bool> SendEmailSafely(SendMailGatewayModel model)
    {
        try
        {
            var result = await _gatewayService.SendMailAsync(model);
            
            if (result?.HttpResponse?.IsSuccess == true)
            {
                _logger.LogInformation($"Email sent successfully. MessageId: {result.MessageId}");
                return true;
            }
            
            _logger.LogWarning($"Email send failed. Status: {result?.HttpResponse?.StatusCode}, Error: {result?.HttpResponse?.ExceptionMessage}");
            return false;
        }
        catch (BaseGatewayException ex)
        {
            _logger.LogError(ex, "Gateway specific error occurred");
            return false;
        }
        catch (NotFoundAttachmentFileException ex)
        {
            _logger.LogError(ex, "Attachment file error occurred");
            return false;
        }
        catch (ArgumentNullException ex)
        {
            _logger.LogError(ex, "Configuration error occurred");
            return false;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Unexpected error occurred while sending email");
            return false;
        }
    }
}

📚 API Reference

IDevaGatewayService Interface

public interface IDevaGatewayService
{
    /// <summary>
    /// Email gönderme servisi
    /// Mailjet adapter'ı kullanarak email gönderir
    /// </summary>
    /// <param name="model">Email gönderme modeli</param>
    /// <returns>Email gönderim sonucu</returns>
    Task<SendMailGatewayDto?> SendMailAsync(SendMailGatewayModel model);
    
    /// <summary>
    /// SMS gönderme servisi
    /// Türk Telekom veya NetGSM adapter'ı kullanarak SMS gönderir
    /// </summary>
    /// <param name="model">SMS gönderme modeli</param>
    /// <returns>SMS gönderim sonucu</returns>
    Task<SendSmsGatewayDto?> SendSmsAsync(SendSmsGatewayModel model);
}

SendMailGatewayModel

public class SendMailGatewayModel
{
    /// <summary>Alıcı email adresleri (zorunlu)</summary>
    public string[] To { get; set; }                    
    
    /// <summary>Kopya alıcıları (isteğe bağlı)</summary>
    public string[] Cc { get; set; }                    
    
    /// <summary>Gizli kopya alıcıları (isteğe bağlı)</summary>
    public string[] Bcc { get; set; }                   
    
    /// <summary>Email konusu (zorunlu)</summary>
    public string Subject { get; set; }                 
    
    /// <summary>Plain text içerik (isteğe bağlı)</summary>
    public string Text { get; set; }                    
    
    /// <summary>HTML içerik (isteğe bağlı)</summary>
    public string Html { get; set; }                    
    
    /// <summary>Ek dosyalar (isteğe bağlı)</summary>
    public SendMailGatewayModelAttachments Attachments { get; set; } 
    
    /// <summary>
    /// Hata yönetim stratejisi
    /// false: Exception fırlat, true: Error response döndür
    /// </summary>
    public bool ReturnException { get; set; } = false; 
}

SendSmsGatewayModel

public class SendSmsGatewayModel
{
    /// <summary>Alıcı telefon numarası (zorunlu)</summary>
    public string To { get; set; }        
    
    /// <summary>SMS mesajı (zorunlu)</summary>
    public string Message { get; set; }   
    
    /// <summary>
    /// Hata yönetim stratejisi
    /// false: Exception fırlat, true: Error response döndür
    /// </summary>
    public bool ReturnException { get; set; } = false; 
}

SendMailGatewayModelAttachments

public class SendMailGatewayModelAttachments
{
    /// <summary>Ek dosyalar listesi</summary>
    public SendMailGatewayModelAttachment[] Files { get; set; }
    
    /// <summary>
    /// Dosya okuma hatalarında exception fırlatılsın mı?
    /// true: Exception fırlat, false: Dosyayı atla
    /// </summary>
    public bool ShowFileExceptions { get; set; } = false;
}

SendMailGatewayModelAttachment

public class SendMailGatewayModelAttachment
{
    /// <summary>Dosya yolu (File sistem kullanımı)</summary>
    public string FilePath { get; set; }
    
    /// <summary>Base64 attachment modeli</summary>
    public SendMailGatewayModelAttachmentBase64 Base64Model { get; set; }
    
    /// <summary>Stream attachment modeli</summary>
    public SendMailGatewayModelAttachmentStream StreamModel { get; set; }
    
    /// <summary>Byte array attachment modeli</summary>
    public SendMailGatewayModelAttachmentBytes BytesModel { get; set; }
}

🔧 Troubleshooting

Yaygın Hatalar ve Çözümleri

1. "Adapter config does not exist" Hatası

Sebep: İlgili adapter yapılandırması bulunamıyor.

Çözüm: appsettings.json'da doğru adapter değerlerini kontrol edin:

{
  "DevaGateway": {
    "Adapters": [
      {
        "Adapter": 1, // Mailjet için
        "PublicKey": "your-key",
        "SecretKey": "your-secret"
      }
    ]
  }
}
2. "API URL cannot be null or empty" Hatası

Sebep: ApiUrl yapılandırması eksik.

Çözüm: appsettings.json'a ApiUrl ekleyin:

{
  "DevaGateway": {
    "ApiUrl": "https://your-domain.com"
  }
}
3. 401 Unauthorized Hatası

Sebep: API anahtarları geçersiz.

Çözüm:

  • PublicKey ve SecretKey değerlerini kontrol edin
  • Adapter sağlayıcısından yeni anahtarlar alın
  • Anahtarların doğru adapter tipine ait olduğunu kontrol edin
4. Attachment Dosya Bulunamadı Hatası

Sebep: Belirtilen dosya yolu geçersiz.

Çözüm:

  • Dosya yolunu kontrol edin
  • ShowFileExceptions = false ayarını kullanarak hatayı görmezden gelin
Attachments = new SendMailGatewayModelAttachments
{
    ShowFileExceptions = false, // Dosya bulunamazsa atla
    Files = attachmentFiles
}
5. Configuration Validation Hataları

Sebep: Zorunlu alanlar eksik veya geçersiz.

Çözüm: Validation hatalarını kontrol edin:

try 
{
    builder.Services.AddDevaGateway(builder.Configuration);
}
catch (OptionsValidationException ex)
{
    Console.WriteLine($"Configuration validation failed: {ex.Message}");
    foreach (var failure in ex.Failures)
    {
        Console.WriteLine($"- {failure}");
    }
}

Debug İpuçları

1. Response Logging
var result = await _gatewayService.SendMailAsync(emailModel);

// Detaylı logging
_logger.LogInformation($"Email Response - Status: {result?.HttpResponse?.StatusCode}");
_logger.LogInformation($"Email Response - Success: {result?.HttpResponse?.IsSuccess}");
_logger.LogInformation($"Email Response - Message ID: {result?.MessageId}");

if (!result?.HttpResponse?.IsSuccess == true)
{
    _logger.LogWarning($"Email failed - Error: {result?.HttpResponse?.ExceptionMessage}");
}
2. Configuration Testing
// Startup'ta configuration test
public void ConfigureServices(IServiceCollection services)
{
    var config = Configuration.GetSection("DevaGateway").Get<DevaGatewayConfig>();
    
    if (string.IsNullOrEmpty(config?.ApiUrl))
        throw new InvalidOperationException("DevaGateway:ApiUrl is required");
    
    if (config.Adapters?.Any() != true)
        throw new InvalidOperationException("At least one adapter must be configured");
        
    services.AddDevaGateway(Configuration);
}
3. Network Connectivity Test
public async Task<bool> TestGatewayConnectivity()
{
    try
    {
        using var httpClient = new HttpClient();
        httpClient.Timeout = TimeSpan.FromSeconds(10);
        
        var response = await httpClient.GetAsync("https://your-domain.com/health");
        
        _logger.LogInformation($"Gateway connectivity test - Status: {response.StatusCode}");
        return response.IsSuccessStatusCode;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Gateway connectivity test failed");
        return false;
    }
}
4. Memory Usage Monitoring
public async Task SendLargeEmailAsync()
{
    var initialMemory = GC.GetTotalMemory(false);
    
    try
    {
        // Email gönder
        var result = await _gatewayService.SendMailAsync(largeEmailModel);
        
        var finalMemory = GC.GetTotalMemory(false);
        var memoryUsed = finalMemory - initialMemory;
        
        _logger.LogInformation($"Memory used for email: {memoryUsed / 1024 / 1024} MB");
    }
    finally
    {
        GC.Collect(); // Force garbage collection
    }
}

Performance Önerileri

1. Attachment Optimization
// ❌ Kötü - List<byte> kullanımı
private List<byte> ReadFileSlow(Stream stream)
{
    var bytes = new List<byte>();
    // Yavaş implementation
}

// ✅ İyi - MemoryStream kullanımı
private byte[] ReadFileFast(Stream stream)
{
    using var memoryStream = new MemoryStream();
    stream.CopyTo(memoryStream);
    return memoryStream.ToArray();
}
2. Async/Await Best Practices
// ✅ Paralel email gönderimi
var emailTasks = new List<Task<SendMailGatewayDto?>>();

foreach (var recipient in recipients)
{
    var emailModel = CreateEmailModel(recipient);
    emailTasks.Add(_gatewayService.SendMailAsync(emailModel));
}

var results = await Task.WhenAll(emailTasks);
3. Memory Management
// ✅ Using statements ile resource management
public async Task SendEmailWithAttachmentsAsync()
{
    using var fileStream1 = File.OpenRead(@"C:\file1.pdf");
    using var fileStream2 = File.OpenRead(@"C:\file2.pdf");
    
    var emailModel = new SendMailGatewayModel
    {
        // ... email properties
        Attachments = new SendMailGatewayModelAttachments
        {
            Files = new[]
            {
                new SendMailGatewayModelAttachment
                {
                    StreamModel = new SendMailGatewayModelAttachmentStream
                    {
                        FileName = "file1.pdf",
                        Stream = fileStream1
                    }
                }
            }
        }
    };
    
    var result = await _gatewayService.SendMailAsync(emailModel);
    
    // Streams otomatik olarak dispose edilir
}

Made with ❤️ by Deva Yazılım

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated