CORE.HELPER 1.0.0.4

dotnet add package CORE.HELPER --version 1.0.0.4
NuGet\Install-Package CORE.HELPER -Version 1.0.0.4
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="CORE.HELPER" Version="1.0.0.4" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add CORE.HELPER --version 1.0.0.4
#r "nuget: CORE.HELPER, 1.0.0.4"
#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.
// Install CORE.HELPER as a Cake Addin
#addin nuget:?package=CORE.HELPER&version=1.0.0.4

// Install CORE.HELPER as a Cake Tool
#tool nuget:?package=CORE.HELPER&version=1.0.0.4

WebP-wrapper

Wrapper for libwebp in C#. The most complete wrapper in pure managed C#.

Exposes Simple Decoding and Encoding API, Advanced Decoding and Encoding API (with statistics of compression), Get version library and WebPGetFeatures (info of any WebP file). Exposed get PSNR, SSIM or LSIM distortion metrics.

The wrapper is in safe managed code in one class. No need for external dll except libwebp_x86.dll(included v0.4.4) and libwebp_x64.dll (included v1.2.1). The wrapper works in 32, 64 bit or ANY (auto swith to the appropriate library).

The code is commented and includes simple examples for using the wrapper.

Decompress Functions:

Load WebP image for WebP file

using (WebP webp = new WebP())
  Bitmap bmp = webp.Load("test.webp");

Decode WebP filename to bitmap and load in PictureBox container

byte[] rawWebP = File.ReadAllBytes("test.webp");
using (WebP webp = new WebP())
  this.pictureBox.Image = webp.Decode(rawWebP);

Advanced decode WebP filename to bitmap and load in PictureBox container

byte[] rawWebP = File.ReadAllBytes("test.webp");
WebPDecoderOptions decoderOptions = new WebPDecoderOptions();
decoderOptions.use_threads = 1;     //Use multhreading
decoderOptions.flip = 1;   			//Flip the image
using (WebP webp = new WebP())
  this.pictureBox.Image = webp.Decode(rawWebP, decoderOptions);

Get thumbnail with 200x150 pixels in fast/low quality mode

using (WebP webp = new WebP())
	this.pictureBox.Image = webp.GetThumbnailFast(rawWebP, 200, 150);

Get thumbnail with 200x150 pixels in slow/high quality mode

using (WebP webp = new WebP())
	this.pictureBox.Image = webp.GetThumbnailQuality(rawWebP, 200, 150);

Compress Functions:

Save bitmap to WebP file

Bitmap bmp = new Bitmap("test.jpg");
using (WebP webp = new WebP())
  webp.Save(bmp, 80, "test.webp");

Encode to memory buffer in lossy mode with quality 75 and save to file

byte[] rawWebP = File.ReadAllBytes("test.jpg");
using (WebP webp = new WebP())
  rawWebP = webp.EncodeLossy(bmp, 75);
File.WriteAllBytes("test.webp", rawWebP); 

Encode to memory buffer in lossy mode with quality 75 and speed 9. Save to file

byte[] rawWebP = File.ReadAllBytes("test.jpg");
using (WebP webp = new WebP())
  rawWebP = webp.EncodeLossy(bmp, 75, 9);
File.WriteAllBytes("test.webp", rawWebP); 

Encode to memory buffer in lossy mode with quality 75, speed 9 and get information. Save to file

byte[] rawWebP = File.ReadAllBytes("test.jpg");
using (WebP webp = new WebP())
  rawWebP = webp.EncodeLossy(bmp, 75, 9, true);
File.WriteAllBytes("test.webp", rawWebP); 

Encode to memory buffer in lossless mode and save to file

byte[] rawWebP = File.ReadAllBytes("test.jpg");
using (WebP webp = new WebP())
  rawWebP = webp.EncodeLossless(bmp);
File.WriteAllBytes("test.webp", rawWebP); 

Encode to memory buffer in lossless mode with speed 9 and save to file

byte[] rawWebP = File.ReadAllBytes("test.jpg");
using (WebP webp = new WebP())
  rawWebP = webp.EncodeLossless(bmp, 9);
File.WriteAllBytes("test.webp", rawWebP); 

Encode to memory buffer in near lossless mode with quality 40 and speed 9 and save to file

byte[] rawWebP = File.ReadAllBytes("test.jpg");
using (WebP webp = new WebP())
  rawWebP = webp.EncodeNearLossless(bmp, 40, 9);
File.WriteAllBytes("test.webp", rawWebP); 

Another Functions:

Get version of libwebp.dll

using (WebP webp = new WebP())
  string version = "libwebp.dll v" + webp.GetVersion();

Get info from WebP file

byte[] rawWebp = File.ReadAllBytes(pathFileName);
using (WebP webp = new WebP())
  webp.GetInfo(rawWebp, out width, out height, out has_alpha, out has_animation, out format);
MessageBox.Show("Width: " + width + "\n" +
                "Height: " + height + "\n" +
                "Has alpha: " + has_alpha + "\n" +
                "Is animation: " + has_animation + "\n" +
                "Format: " + format);

Get PSNR, SSIM or LSIM distortion metric between two pictures

int metric = 0;  //0 = PSNR, 1= SSIM, 2=LSIM
Bitmap bmp1 = Bitmap.FromFile("image1.png");
Bitmap bmp2 = Bitmap.FromFile("image2.png");
using (WebP webp = new WebP())
	result = webp.GetPictureDistortion(source, reference, metric);
	                    MessageBox.Show("Red: " + result[0] + "dB.\nGreen: " + result[1] + "dB.\nBlue: " + result[2] + "dB.\nAlpha: " + result[3] + "dB.\nAll: " + result[4] + "dB.", "PSNR");

MessageBox.Show("Red: " + result[0] + dB\n" +
                "Green: " + result[1] + "dB\n" +
                "Blue: " + result[2] + "dB\n" +
                "Alpha: " + result[3] + "dB\n" +
                "All: " + result[4] + "dB\n");

nQuant.NET

nQuant is a .NET color quantizer producing high quality indexed PNG images using an algorithm optimized for the highest quality possible.

This Fork

This fork was made to support creating 4-bit images, as the original only supports creating 8-bit images. The public interface is kept completely compatible with the original, so the same code will do the same thing.

Usage

Usage is the same as the standard nQuant library, with the only exception being a new optional parameter on WuQuantizer.QuantizeImage. It's modified to:

Image QuantizeImage(Bitmap image, int alphaThreshold = 10, int alphaFader = 70, int maxColors = 256);
  • image: An image in 32-bit ARGB format.
  • alphaThreshold: All colors with an alpha value equal to or less than this will be considered fully transparent.
  • alphaFader: Alpha values will be normalized to the nearest multiple of this value.
  • maxColors: The maximum number of colors in the output image format.
    • 256: Return an 8-bit image containing 256 colors.
    • 16: Return a 4-bit image containing 16 colors.
    • 2: Return a 1-bit image containing 2 colors. (Note that the last color is transparent, so each pixel will either be fully transparent or not.)

AltoHttp download

 private void init()
{
	var defaultFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
	var defaultFileName = "default.unknown";
	var defaultSavePath = Path.Combine(defaultFolder, defaultFileName);
	downloader = new HttpDownloader("https://sabnzbd.org/tests/internetspeed/50MB.bin", defaultSavePath);
	downloader.StatusChanged += downloader_StatusChanged;
	downloader.DownloadInfoReceived += downloader_DownloadInfoReceived;
	downloader.DownloadCompleted += downloader_DownloadCompleted;
	downloader.ProgressChanged += downloader_ProgressChanged;
	downloader.ErrorOccured += downloader_ErrorOccured;
	downloader.Start();
}
 void downloader_ErrorOccured(object sender, ErrorEventArgs e)
{
	var ex = e.GetException();
	if (ex is FileValidationFailedException)
		downloader.Pause();
	//   MessageBox.Show("Error: " + e.GetException().Message + " " + e.GetException().StackTrace);
}
void downloader_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
	var lblTotalBytesReceived = string.Format("{0} / {1}",
		 e.TotalBytesReceived.ToHumanReadableSize(),
		 downloader.Info.Length > 0 ? downloader.Info.Length.ToHumanReadableSize() : "Unknown");
	var lblProgress = e.Progress.ToString("0.00") + "%";
	var lblSpeed = e.SpeedInBytes.ToHumanReadableSize() + "/s";
	processExcute.Value = e.Progress;
	txtValue.Text = $"{lblTotalBytesReceived} - {lblProgress} {lblSpeed} ";
	FushRam();
}
void downloader_DownloadCompleted(object sender, EventArgs e)
{
	App.Current.Shutdown();
}
void downloader_DownloadInfoReceived(object sender, EventArgs e)
{
	var saveDirectory = Path.GetDirectoryName(downloader.FullFileName);
	var serverFileName = downloader.Info.ServerFileName;

	var newFilePath = Path.Combine(saveDirectory, serverFileName);

	downloader.FullFileName = newFilePath;

	var lblFileName = downloader.Info.ServerFileName;
	var lblResumeability = downloader.Info.AcceptRange ? "Yes" : "No";
	var lblSize = downloader.Info.Length > 0 ? downloader.Info.Length.ToHumanReadableSize() : "Unknown";
	var lblIsChunked = downloader.Info.IsChunked ? "Yes" : "No";
}
void downloader_StatusChanged(object sender, StatusChangedEventArgs e)
	{

	}

Dapper-Parameters

Project to extend on Dynamic Paramters for Dapper. Currently only has a method to handle User-Defined Table Types.

Example

Given that we have a User-Defined Table Type of: [dbo].[IntList] that is defined as such:

CREATE TYPE [dbo].[IntList] AS TABLE(
	[IntValue] [int] NOT NULL
)

All we need is to have a csharp class that is defined the same way as our type (similar to the way Dapper maps query results):

// Class Name doesn't matter
public class IntListType 
{
  // Must match Table Type name!
  public int IntValue { get; set; }
}

Then put it all together:

var ids = new List<int>{1,2,3,4};
var intList = ids.Select(x => new IntListType { IntValue = x });

var parameters = new DynamicParameters();
parameters.AddTable("@sprocParameterName", "[dbo].[IntList]", intList);

connection.Execute("storedProcedure", parameters, CommandType.StoredProcedure);

###If you have multipe values in your table type such as:

CREATE TYPE [dbo].[TestType] AS TABLE(
	[TestValue1] [int] NOT NULL,
  [TestValue2] [nvarchar(50)] NOT NULL
)

Your matching C# class properties must match exact order:

GOOD

public class TestType 
{
  public int TestValue1 { get; set; }
  public string TestValue2 { get; set; }
}

BAD

public class TestType 
{
  public string TestValue2 { get; set; } // This comes second in your TestType sql definition so it needs to be second in this class
  public int TestValue1 { get; set; }
}

*Does not support anything other than flat types, so no nested types

##SocketIO SocketIOSharp is a Socket.IO protocol revision 4 library based on Engine.IO and WebSocket protocol. It depends on EngineIOSharp to use Engine.IO protocol.

Usage

Client

Namespace

using CORE.HELPER.SocketIO;
using EngineIOSharp.Common.Enum;

Constructor

SocketIOClient client = new SocketIOClient(new SocketIOClientOption(EngineIOScheme.http, "localhost", 9001));
SocketIOClientOption
  • Essential Parameters

    • Scheme : Scheme to connect to. It can be EngineIOScheme.http or EngineIOScheme.https. Internally, it supports ws and wss.

    • Host : Host to connect to.

    • Port : Port to connect to.

  • Optional Parameters

    • PolicyPort : Port the policy server listens on. Defaults to 843.

    • Path : Path to connect to. Defaults to "/socket.io".

    • Reconnection : Whether to reconnect to server after Socket.IO client is closed or not.

    • ReconnectionAttempts : Number of reconnection attempts before giving up.

    • ReconnectionDelay : How ms to initially wait before attempting a new reconnection.

    • ReconnectionDelayMax : Maximum amount of time to wait between reconnections. Each attempt increases the ReconnectionDelay by 2x along with a randomization.

    • RandomizationFactor : 0 ⇐ RandomizationFactor ⇐ 1.

    • Query : Parameters that will be passed for each request to the server. Defaults to null.

    • Upgrade : Whether the client should try to upgrade the transport. Defaults to true.

    • RemeberUpgrade : Whether the client should bypass normal upgrade process when previous websocket connection is succeeded. Defaults to false.

    • ForceBase64 : Forces base 64 encoding for transport. Defaults to false.

    • WithCredentials : Whether to include credentials such as cookies, authorization headers, TLS client certificates, etc. with polling requests. Defaults to false.

    • TimestampRequests : Whether to add the timestamp with each transport request. Polling requests are always stamped. Defaults to null.

    • TimestampParam : Timestamp parameter. Defaults to "t".

    • Polling : Whether to include polling transport. Defaults to true.

    • PollingTimeout : Timeout for polling requests in milliseconds. Defaults to 0, which waits indefinitely.

    • WebSocket : Whether to include websocket transport. Defaults to true.

    • WebSocketSubprotocols : List of websocket subprotocols. Defaults to null.

    • ExtraHeaders : Headers that will be passed for each request to the server. Defaults to null.

    • ClientCertificates : The collection of security certificates that are associated with each request. Defaults to null.

    • ClientCertificateSelectionCallback : Callback used to select the certificate to supply to the server. Defaults to null.

    • ServerCertificateValidationCallback : Callback method to validate the server certificate. Defaults to null and server certificate will be always validated.

Connect

client.Connect();

Disconnect

client.Close();

or

client.Dispose();

Since SocketIOClient implements IDisposable interface, it will be automatically disconnect when SocketIOClient.Dispose is called.

Handlers

For convenient usage, it is implemented to can be used as Javascript style.

Event handlers
client.On(SocketIOClient.Event.CONNECTION, () =>
{
  Console.WriteLine("Connected!");
});

client.On(SocketIOClient.Event.DISCONNECT, () =>
{
  Console.WriteLine("Disconnected!");
});

client.On(SocketIOClient.Event.ERROR, (JToken[] Data) => // Type of argument is JToken[].
{
  if (Data != null && Data.Length > 0 && Data[0] != null)
  {
    Console.WriteLine("Error : " + Data[0]);
  }
  else
  {
    Console.WrtieLine("Unkown Error");
  }
});

client.On("message", (Data) => // Argument can be used without type.
{
  if (Data != null && Data.Length > 0 && Data[0] != null)
  {
    Console.WriteLine("Message : " + Data[0]);
  }
});

client.On("CustomEvent", CustomEventHandler); // Handler can be method.
client.On(9001, ItsOverNineThousands); // Type of event is JToken. So, it can be a number.

client.Off(9001, ItsOverNineThousands); // Remove 9001 event handler.
ACK handlers
client.On("ACK1", (SocketIOAckEvent EventArgument) =>
{
  // Type of SocketIOAckEvent.Data is JToken[].
  // Type of SocketIOAckEvent.Callback is Action<JToken[]>.
  
  Console.Write("On event ack1 : " + EventArgument.Data);
});

client.On("ACK2", (EventArgument) => // Argument can be used without type.
{
  Console.Write("On event ack2 : " + EventArgument.Data);
});

client.On("ACK3", CustomAckHandler); // Handler can be method.
client.On(42, LifeTheUniverseAndTheEverything); // Type of event is JToken. So, it can be a number.

client.Off(42, LifeTheUniverseAndTheEverything); // Remove 42 ack handler.
SocketIOClient.Event
public static class Event
{
  public static readonly string CONNECTION = "connection";
  public static readonly string DISCONNECT = "disconnect";
  public static readonly string ERROR = "error";
}

These are the common basic Socket.IO events.

Emit

client.Emit("Event without data and ack");

client.Emit("Event only with data", "Hello world");

client.Emit("Event only with ack, action as lambda", (Data) => Console.WriteLine("ACK : " + Data));
client.Emit("Event only with ack, action as method", Console.WriteLine);

client.Emit("Event with data and ack, action as lambda", 9001, (Data) => Console.WriteLine("ACK : " + Data));
client.Emit("Event with data and ack, action as method", 42, Console.WriteLine);
// Type of data is JToken. So, it can be a number.

Server

Namespace

using CORE.HELPER.SocketIO;

Constructor

SocketIOServer server = new SocketIOServer(new SocketIOServerOption(9001));
SocketIOServerOption
  • Essential Parameters

    • Port : Port to listen.
  • Optional Parameters

    • Path : Path to listen. Defaults to "/socket.io".

    • Secure : Whether to secure connections. Defatuls to false.

    • PingTimeout : How many ms without a pong packet to consider the connection closed. Defatuls to 5000.

    • PingInterval : How many ms before sending a new ping packet. Defatuls to 25000.

    • UpgradeTimeout : How many ms before an uncompleted transport upgrade is cancelled. Defatuls to 10000.

    • Polling : Whether to accept polling transport. Defatuls to true.

    • WebSocket : Whether to accept websocket transport. Defatuls to true.

    • AllowUpgrade : Whether to allow transport upgrade. Defatuls to true.

    • SetCookie : Whether to use cookie. Defatuls to true.

    • SIDCookieName : Name of sid cookie. Defatuls to "io".

    • Cookies : Configuration of the cookie that contains the client sid to send as part of handshake response headers. This cookie might be used for sticky-session. Defatuls to null.

    • AllowHttpRequest : A function that receives a given handshake or upgrade http request as its first parameter, and can decide whether to continue or not. Defatuls to null.

    • AllowWebSocket : A function that receives a given handshake or upgrade websocket connection as its first parameter, and can decide whether to continue or not. Defatuls to null.

    • InitialData : An optional packet which will be concatenated to the handshake packet emitted by Engine.IO. Defatuls to null.

    • ServerCertificate : The certificate used to authenticate the server. Defatuls to null.

    • ClientCertificateValidationCallback : Callback used to validate the certificate supplied by the client. Defatuls to null and client certificate will be always validated.

Start

server.Start();

Stop

server.Stop();

or

server.Dispose();

Since SocketIOServer implements IDisposable interface, it will be automatically stoped when SocketIOServer.Dispose is called.

Connection

For convenient usage, it is implemented to can be used as Javascript style.

server.OnConnection((SocketIOSocket socket) =>
{
  Console.WriteLine("Client connected!");

  socket.On("input", (Data) =>
  {
    foreach (JToken Token in Data)
    {
      Console.Write(Token + " ");
    }

    Console.WriteLine();
    socket.Emit("echo", Data);
  });

  socket.On(SocketIOEvent.DISCONNECT, () =>
  {
    Console.WriteLine("Client disconnected!");
  });
});
SocketIOSocket
  • SocketIOSocket is a type of parameter in SocketIOServer.OnConnection event callback. It can be used similarly as SocketIOClient.
Disconnect
socket.Close();

or

socket.Dispose();

Since SocketIOSocket implements IDisposable interface, it will be automatically disconnected when SocketIOSocket.Dispose is called.

Handlers

For convenient usage, it is implemented to can be used as Javascript style.

Event handlers
client.On(SocketIOClient.Event.DISCONNECT, () =>
{
  Console.WriteLine("Disconnected!");
});

client.On(SocketIOClient.Event.ERROR, (JToken[] Data) => // Type of argument is JToken[].
{
  if (Data != null && Data.Length > 0 && Data[0] != null)
  {
    Console.WriteLine("Error : " + Data[0]);
  }
  else
  {
    Console.WrtieLine("Unkown Error");
  }
});

client.On("message", (Data) => // Argument can be used without type.
{
  if (Data != null && Data.Length > 0 && Data[0] != null)
  {
    Console.WriteLine("Message : " + Data[0]);
  }
});

client.On("CustomEvent", CustomEventHandler); // Handler can be method.
client.On(9001, ItsOverNineThousands); // Type of event is JToken. So, it can be a number.

client.Off(9001, ItsOverNineThousands); // Remove 9001 event handler.
  • There is no SocketIOSocket.On(SocketIOEvent.CONNECTION) event since it is already opened when SocketIOServer.OnConnection event callback is called.
ACK handlers
client.On("ACK1", (SocketIOAckEvent EventArgument) =>
{
  // Type of SocketIOAckEvent.Data is JToken[].
  // Type of SocketIOAckEvent.Callback is Action<JToken[]>.
  
  Console.Write("On event ack1 : " + EventArgument.Data);
});

client.On("ACK2", (EventArgument) => // Argument can be used without type.
{
  Console.Write("On event ack2 : " + EventArgument.Data);
});

client.On("ACK3", CustomAckHandler); // Handler can be method.
client.On(42, LifeTheUniverseAndTheEverything); // Type of event is JToken. So, it can be a number.

client.Off(42, LifeTheUniverseAndTheEverything); // Remove 42 ack handler.
Emit
client.Emit("Event without data and ack");

client.Emit("Event only with data", "Hello world");

client.Emit("Event only with ack, action as lambda", (Data) => Console.WriteLine("ACK : " + Data));
client.Emit("Event only with ack, action as method", Console.WriteLine);

client.Emit("Event with data and ack, action as lambda", 9001, (Data) => Console.WriteLine("ACK : " + Data));
client.Emit("Event with data and ack, action as method", 42, Console.WriteLine);
// Type of data is JToken. So, it can be a number.

Emit

server.Emit("Event without data and ack");

server.Emit("Event only with data", "Hello world");

server.Emit("Event only with ack, action as lambda", (Data) => Console.WriteLine("ACK : " + Data));
server.Emit("Event only with ack, action as method", Console.WriteLine);

server.Emit("Event with data and ack, action as lambda", 9001, (Data) => Console.WriteLine("ACK : " + Data));
server.Emit("Event with data and ack, action as method", 42, Console.WriteLine);
// Type of data is JToken. So, it can be a number.

SignalR.TypedClient

A proof of concept for strongly typed SignalR Clients using Castle.DynamicProxy

Client Code

using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Threading.Tasks;
using SignalR.TypedClient;
using TestCommon;

namespace TestClient
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var builder = new HubConnectionBuilder();
            await Task.Delay(TimeSpan.FromSeconds(3));
            var hub = builder
                .WithUrl("http://localhost:5000/echo")
                .WithAutomaticReconnect()
                // New extension method
                .Build<IEchoHub>();

            // Register a strongly typed class to capture callbacks
            var unregister = hub.RegisterCallbacks(new MyClientCallbacks());
            
            // Connect
            await hub.StartAsync();
            
            // Invoke methods via an interface
            var message = await hub.Invoke.Echo("Some message");
            Console.WriteLine($"Result: {message}");
        }
    }

    public class MyClientCallbacks : IEchoHubClient
    {
        public Task OnMessageReceived(string message)
        {
            Console.WriteLine($"{nameof(OnMessageReceived)} - {message}");
            return Task.CompletedTask;
        }
    }
}

Server Code

using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
using TestCommon;

namespace TestServer
{
    public class EchoHub : Hub<IEchoHubClient>, IEchoHub
    {
        public async Task<string> Echo(string message)
        {
            await Clients.All.OnMessageReceived(message);
            return message;
        }
    }
}
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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
1.0.0.4 522 5/6/2022
1.0.0.2 409 4/23/2022
1.0.0.1 382 4/1/2022