diff --git a/README.md b/README.md index 14786a26a..652ae92c2 100644 --- a/README.md +++ b/README.md @@ -274,7 +274,7 @@ var data = Json.Deserialize(basicJson); ### The `CsvWriter` class -Many projects require the use of CSV files to export and import data. With `CsvWriter` you can easily write objects and data to CSV format. It also provides a useful way to save the data to a file. +Many projects require the use of CSV files to export and import data. With `CsvWriter` you can easily write objects and data to CSV format. It also provides a useful way to save data into a file. [CsvWriter API Doc](https://unosquare.github.io/swan/api/Unosquare.Swan.Formatters.CsvWriter.html) @@ -288,7 +288,7 @@ var basicObj = new List(); using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(basicObj.ToString()))) { - // The writer of the CSV + // The CSV writer var reader = new CsvWriter(stream); }; ``` @@ -301,7 +301,7 @@ You also can write the object into a file or a temporal file. // The list of objects to be written as CSV var basicObj = new List(); // This is where the object is save into a file -CsvWriter.SaveRecords(basicObj, "C:/Users/user/Documents/CsvFile"); +CsvWriter.SaveRecords(basicObj, "C:/Users/user/Documents/CsvFile"); ``` ### The `CsvReader` class @@ -315,14 +315,14 @@ When you need to parse data in CSV files you'll always need an easy way to read This is a way to read CSV formatted string. ```csharp - // The data to be readed + // The data to be read var data = @"Company,OpenPositions,MainTechnology,Revenue - Co,2,""C#, MySQL, JavaScript, HTML5 and CSS3"","500" - Ca,2,""C#, MySQL, JavaScript, HTML5 and CSS3"","600"; + Co,2,""C#, MySQL, JavaScript, HTML5 and CSS3"",500 + Ca,2,""C#, MySQL, JavaScript, HTML5 and CSS3"",600"; using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(data))) { - // The reader of the CSV + // The CSV reader var reader = new CsvReader(stream, true, Encoding.UTF8); }; ``` @@ -335,7 +335,7 @@ From a CSV file, you can read and load the information into a generic list. // The list of object to be written as CSV var basicObj = new List(); // This is where the object is save into a file -CsvWriter.SaveRecords(basicObj, "C:/Users/user/Documents/CsvFile"); +CsvWriter.SaveRecords(basicObj, "C:/Users/user/Documents/CsvFile"); // This is how you can load the records of the CSV file var loadedRecords = CsvReader.LoadRecords("C:/Users/user/Documents/CsvFile"); ``` @@ -410,7 +410,7 @@ session.Recipients.Add("recipient@test.cm"); client.SendMailAsync(session); ``` -#### Example 3: Adding an attatchment with SMTP session state +#### Example 3: Adding an attachment with SMTP session state When using `SmtpSessionState` you have to deal with raw data manipulation, in order to parse MIME attachments [MimeKit](https://www.nuget.org/packages/MimeKit/) is recommended. ```csharp // Create a new session state with a sender address @@ -592,9 +592,9 @@ This time we'll be using both custom validators and attributes ```csharp // using the Runtime's ObjectValidator singleton -Runtime.ObjectValidator.Value.AddValidator(x => !x.Name.Equals("Name"), "Name must not be 'Name'"); +Runtime.ObjectValidator.AddValidator(x => !x.Name.Equals("Name"), "Name must not be 'Name'"); -var res = Runtime.ObjectValidator.Value.Validate(new Simple{ Name = "name", Number = 5, Email ="email@mail.com"}) +var res = Runtime.ObjectValidator.Validate(new Simple{ Name = "name", Number = 5, Email ="email@mail.com"}) ``` @@ -603,7 +603,7 @@ In this example, we'll use the previous `Sample` class to validate an object usi ```csharp // using the Runtime's ObjectValidator singleton -Runtime.ObjectValidator.Value.AddValidator(x => !x.Name.Equals("Name"), "Name must not be 'Name'"); +Runtime.ObjectValidator.AddValidator(x => !x.Name.Equals("Name"), "Name must not be 'Name'"); // using the extension method var res = new Simple{ Name = "name", Number = 5, Email ="email@mail.com"}.IsValid(); @@ -662,28 +662,28 @@ A simple [Publisher-Subscriber pattern](https://en.wikipedia.org/wiki/Publish%E2 [MessageHub API Doc](https://unosquare.github.io/swan/api/Unosquare.Swan.Components.IMessageHub.html) -In many scenarios you need a way to know when something happens to an object, there are usually two ways of achieving this: constantly checking the object's properties or using the pub-sub pattern. To avoid any problems caused by the former method like a possible modification of the object's properties it is a good practice to use the latter. With the pub-sub pattern, any object can "subscribe" to another object's event if the other object "publishes" a message the event is triggered and the custom content of the message is sent. Neither the publisher nor the subscriber knows the existence of one another, therefore the publisher does not directly notify its subscribers, instead there is another component called MessageHub which is known by both(subscriber and publisher) and that filters all incoming messages and distributes them accordingly. +In many scenarios you need a way to know when something happens to an object, there are usually two ways of achieving this: constantly checking the object's properties or using the pub-sub pattern. To avoid any problems caused by the former method like a possible modification of the object's properties it is a good practice to use the latter. With the pub-sub pattern, any object can "subscribe" to the publisher's publish event. When a message is "published" the event is triggered and the custom content of the message is sent. Neither the publisher nor the subscriber knows the existence of one another, therefore the publisher does not directly notify its subscribers, instead there is another component called MessageHub which is known by both(subscriber and publisher) and that filters all incoming messages and distributes them accordingly. #### Example 1: Subscribing to a MessageHub A simple example using the DependencyContainer discussed above. Keep in mind that in this example both the subscription and the message sending are done in the same place but this is only for explanatory purposes. ``` csharp -// Using DependencyContainer to create an instance of MessageHub +// use DependencyContainer to create an instance of MessageHub var messageHub = DependencyContainer.Current.Resolve() as MessageHub; - // Here we create an instance of the publisher class which has a string as its content + // create an instance of the publisher class which has a string as its content var message = new MessageHubGenericMessage(this, "SWAN"); - // Then this object subscribes to the publisher's event and just prints its content which is a string + // subscribe to the publisher's event and just print its content which is a string // a token is returned which can be used to unsubscribe later on var token = messageHub.Subscribe>(m => m.Content.Info()); - // We publish a message and SWAN should be printed on the console + //publish a message and SWAN should be printed on the console messageHub.Publish(message); - // And lastly unsuscribe, we will no longer receive any messages - MessageHub.Unsubscribe>(token); + // unsuscribe, we will no longer receive any messages + messageHub.Unsubscribe>(token); ``` ### The `LDAPConnection` class @@ -775,7 +775,7 @@ An easy way to deal with attributes modification is by calling the Modify method connection.Disconnect(); ``` ### The `ProcessRunner` class -A class that provides methods that helps us create external process and capture their output. +A class that provides methods that helps us create external processes and capture their output. [ProcessRunner API Doc](https://unosquare.github.io/swan/api/Unosquare.Swan.Components.ProcessRunner.html) diff --git a/src/Unosquare.Swan.Lite/Abstractions/SettingsProvider.cs b/src/Unosquare.Swan.Lite/Abstractions/SettingsProvider.cs index 19a195e18..d8d249fcb 100644 --- a/src/Unosquare.Swan.Lite/Abstractions/SettingsProvider.cs +++ b/src/Unosquare.Swan.Lite/Abstractions/SettingsProvider.cs @@ -14,6 +14,34 @@ /// /// Represents a provider to save and load settings using a plain JSON file /// + /// + /// The following example shows how to save and load settings. + /// + /// using Unosquare.Swan.Abstractions; + /// + /// public class Example + /// { + /// public static void Main() + /// { + /// // get user from settings + /// var user = SettingsProvider<Settings>.Instance.Global.User; + /// + /// // modify the port + /// SettingsProvider<Settings>.Instance.Global.Port = 20; + /// + /// // if we want these settings to persist + /// SettingsProvider<Settings>.Instance.PersistGlobalSettings(); + /// } + /// + /// public class Settings + /// { + /// public int Port { get; set; } = 9696; + /// + /// public string User { get; set; } = "User"; + /// } + /// } + /// + /// /// The type of settings model public class SettingsProvider : SingletonBase> diff --git a/src/Unosquare.Swan.Lite/Components/ArgumentParser.cs b/src/Unosquare.Swan.Lite/Components/ArgumentParser.cs index 7e7145e38..ebcdfc697 100644 --- a/src/Unosquare.Swan.Lite/Components/ArgumentParser.cs +++ b/src/Unosquare.Swan.Lite/Components/ArgumentParser.cs @@ -10,6 +10,103 @@ namespace Unosquare.Swan.Components /// Provides methods to parse command line arguments. /// Based on CommandLine (Copyright 2005-2015 Giacomo Stelluti Scala and Contributors.) /// + /// + /// The following example shows how to parse CLI arguments into objects. + /// + /// class Example + /// { + /// using System; + /// using Unosquare.Swan; + /// using Unosquare.Swan.Attributes; + /// + /// static void Main(string[] args) + /// { + /// // create an instance of the Options class + /// var options = new Options(); + /// + /// // parse the supplied command-line arguments into the options object + /// var res = Runtime.ArgumentParser.ParseArguments(args, options); + /// } + /// + /// class Options + /// { + /// [ArgumentOption('v', "verbose", HelpText = "Set verbose mode.")] + /// public bool Verbose { get; set; } + /// + /// [ArgumentOption('u', Required = true, HelpText = "Set user name.")] + /// public string Username { get; set; } + /// + /// [ArgumentOption('n', "names", Separator = ',', + /// Required = true, HelpText = "A list of files separated by a comma")] + /// public string[] Files { get; set; } + /// + /// [ArgumentOption('p', "port", DefaultValue = 22, HelpText = "Set port.")] + /// public int Port { get; set; } + /// + /// [ArgumentOption("color", DefaultValue = ConsoleColor.Red, + /// HelpText = "Set a color.")] + /// public ConsoleColor Color { get; set; } + /// } + /// } + /// + /// The following code describes how to parse CLI verbs. + /// + /// class Example2 + /// { + /// using Unosquare.Swan; + /// using Unosquare.Swan.Attributes; + /// + /// static void Main(string[] args) + /// { + /// // create an instance of the VerbOptions class + /// var options = new VerbOptions(); + /// + /// // parse the supplied command-line arguments into the options object + /// var res = Runtime.ArgumentParser.ParseArguments(args, options); + /// + /// // if there were no errors parsing + /// if (res) + /// { + /// if(options.Run != null) + /// { + /// // run verb was selected + /// } + /// + /// if(options.Print != null) + /// { + /// // print verb was selected + /// } + /// } + /// + /// // flush all error messages + /// Terminal.Flush(); + /// } + /// + /// class VerbOptions + /// { + /// [VerbOption("run", HelpText = "Run verb.")] + /// public RunVerbOption Run { get; set; } + /// + /// [VerbOption("print", HelpText = "Print verb.")] + /// public PrintVerbOption Print { get; set; } + /// } + /// + /// class RunVerbOption + /// { + /// [ArgumentOption('o', "outdir", HelpText = "Output directory", + /// DefaultValue = "", Required = false)] + /// public string OutDir { get; set; } + /// } + /// + /// class PrintVerbOption + /// { + /// [ArgumentOption('t', "text", HelpText = "Text to print", + /// DefaultValue = "", Required = false)] + /// public string Text { get; set; } + /// } + /// } + /// + /// public class ArgumentParser { private const char Dash = '-'; diff --git a/src/Unosquare.Swan.Lite/Components/Benchmark.cs b/src/Unosquare.Swan.Lite/Components/Benchmark.cs index 9da6e2822..4c8d69407 100644 --- a/src/Unosquare.Swan.Lite/Components/Benchmark.cs +++ b/src/Unosquare.Swan.Lite/Components/Benchmark.cs @@ -9,6 +9,30 @@ /// /// A simple benchmarking class. /// + /// + /// The following code demonstrates how to create a simple benchmark. + /// + /// namespace Examples.Benchmark.Simple + /// { + /// using Unosquare.Swan.Components; + /// + /// public class SimpleBenchmark + /// { + /// public static void Main() + /// { + /// using (Benchmark.Start("Test")) + /// { + /// // do some logic in here + /// } + /// + /// // dump results into a string + /// var results = Benchmark.Dump(); + /// } + /// } + /// + /// } + /// + /// public static class Benchmark { private static readonly object SyncLock = new object(); diff --git a/src/Unosquare.Swan.Lite/Components/ObjectMapper.cs b/src/Unosquare.Swan.Lite/Components/ObjectMapper.cs index d4389d20a..82a9be160 100644 --- a/src/Unosquare.Swan.Lite/Components/ObjectMapper.cs +++ b/src/Unosquare.Swan.Lite/Components/ObjectMapper.cs @@ -13,6 +13,69 @@ /// /// The extension methods like CopyPropertiesTo use the default behaviour. /// + /// + /// The following code explains how to map an object's properties into an instance of type T + /// + /// using Unosquare.Swan + /// + /// class Example + /// { + /// class Person + /// { + /// public string Name { get; set; } + /// public int Age { get; set; } + /// } + /// + /// static void Main() + /// { + /// var obj = new { Name = "Søren", Age = 42 }; + /// + /// var person = Runtime.ObjectMapper.Map<Person>(obj); + /// } + /// } + /// + /// The following code explains how to explicitly map certain properties. + /// + /// using Unosquare.Swan + /// + /// class Example + /// { + /// class User + /// { + /// public string Name { get; set; } + /// public Role Role { get; set; } + /// } + /// + /// public class Role + /// { + /// public string Name { get; set; } + /// } + /// + /// class UserDto + /// { + /// public string Name { get; set; } + /// public string Role { get; set; } + /// } + /// + /// static void Main() + /// { + /// // create a User object + /// var person = + /// new User { Name = "Phillip", Role = new Role { Name = "Admin" } }; + /// + /// // create an Object Mapper + /// var mapper = new ObjectMapper(); + /// + /// // map the User's Role.Name to UserDto's Role + /// mapper.CreateMap<User, UserDto>() + /// .MapProperty(d => d.Role, x => x.Role.Name); + /// + /// // apply the previous map and retrieve a UserDto object + /// var destination = mapper.Map<UserDto>(person); + /// } + /// } + /// + /// public class ObjectMapper { private readonly List _maps = new List(); diff --git a/src/Unosquare.Swan.Lite/Components/ObjectValidator.cs b/src/Unosquare.Swan.Lite/Components/ObjectValidator.cs index 9188ac1e8..a7bb0c41f 100644 --- a/src/Unosquare.Swan.Lite/Components/ObjectValidator.cs +++ b/src/Unosquare.Swan.Lite/Components/ObjectValidator.cs @@ -11,6 +11,65 @@ /// /// Represents an object validator /// + /// + /// The following code describes how to perform a simple object validation + /// + /// using Unosquare.Swan.Components; + /// + /// class Example + /// { + /// public static void Main() + /// { + /// // create an instance of ObjectValidator + /// vtor obj = new ObjectValidator(); + /// + /// // Add a validation to the 'Simple' class with a custom error message + /// vtor.AddValidator<Simple>(x => + /// !string.IsNullOrEmpty(x.Name), "Name must not be empty"); + /// + /// // check if object is valid + /// var res = vtor.IsValid(new Simple { Name = "Name" }); + /// } + /// + /// class Simple + /// { + /// public string Name { get; set; } + /// } + /// } + /// + /// + /// The following code shows of to validate an object with a custom validator and some attributes using the Runtime ObjectValidator singleton + /// + /// using Unosquare.Swan.Components; + /// + /// class Example + /// { + /// public static void Main() + /// { + /// // create an instance of ObjectValidator + /// Runtime.ObjectValidator + /// .AddValidator<Simple>(x => + /// !x.Name.Equals("Name"), "Name must not be 'Name'"); + /// + /// // validate object + /// var res = Runtime.ObjectValidator + /// .Validate(new Simple{ Name = "name", Number = 5, Email ="email@mail.com"}) + /// } + /// + /// class Simple + /// { + /// [NotNull] + /// public string Name { get; set; } + /// + /// [Range(1, 10)] + /// public int Number { get; set; } + /// + /// [Email] + /// public string Email { get; set; } + /// } + /// } + /// + /// public class ObjectValidator { private readonly Dictionary>> _predicates = diff --git a/src/Unosquare.Swan.Lite/Components/WaitEventFactory.cs b/src/Unosquare.Swan.Lite/Components/WaitEventFactory.cs index c55054d08..58e9b7607 100644 --- a/src/Unosquare.Swan.Lite/Components/WaitEventFactory.cs +++ b/src/Unosquare.Swan.Lite/Components/WaitEventFactory.cs @@ -8,6 +8,51 @@ namespace Unosquare.Swan.Components /// /// Provides a Manual Reset Event factory with a unified API /// + /// + /// The following example shows how to use the WaitEventFactory class + /// + /// using Unosquare.Swan.Components; + /// + /// public class Example + /// { + /// // create a WaitEvent using the slim version + /// private static readonly IWaitEvent waitEvent = WaitEventFactory.CreateSlim(false); + /// + /// public static void Main() + /// { + /// Task.Factory.StartNew(() => + /// { + /// DoWork(1); + /// }); + /// + /// Task.Factory.StartNew(() => + /// { + /// DoWork(2); + /// }); + /// + /// // send first signal + /// waitEvent.Complete(); + /// waitEvent.Begin(); + /// + /// Thread.Sleep(TimeSpan.FromSeconds(2)); + /// + /// // send second signal + /// waitEvent.Complete(); + /// + /// Console.Readline(); + /// } + /// + /// public static void DoWork(int taskNumber) + /// { + /// $"Data retrieved:{taskNumber}".WriteLine(); + /// waitEvent.Wait(); + /// + /// Thread.Sleep(TimeSpan.FromSeconds(2)); + /// $"All finished up {taskNumber}".WriteLine(); + /// } + /// } + /// + /// public static class WaitEventFactory { #region Factory Methods diff --git a/src/Unosquare.Swan.Lite/Formatters/CsvReader.cs b/src/Unosquare.Swan.Lite/Formatters/CsvReader.cs index 65ac8d362..ff7e8b78a 100644 --- a/src/Unosquare.Swan.Lite/Formatters/CsvReader.cs +++ b/src/Unosquare.Swan.Lite/Formatters/CsvReader.cs @@ -14,7 +14,58 @@ /// transforming CSV lines of text into objects, /// or simply reading the lines of CSV as an array of strings /// - /// + /// + /// + /// The following example describes how to load a list of objects from a CSV file + /// + /// using Unosquare.Swan.Formatters; + /// + /// class Example + /// { + /// class Person + /// { + /// public string Name { get; set; } + /// public int Age { get; set; } + /// } + /// + /// static void Main() + /// { + /// // load records from a CSV file + /// var loadedRecords = + /// CsvReader.LoadRecords<Person>("C:\\Users\\user\\Documents\\file.csv"); + /// + /// // loadedRecords = + /// // [ + /// // { Age = 20, Name = "Artyom" } + /// // { Age = 18, Name = "Aloy" } + /// // ] + /// } + /// } + /// + /// The following code explains how to read a CSV formatted string + /// + /// using Unosquare.Swan.Formatters; + /// using System.Text; + /// using Unosquare.Swan.Formatters; + /// + /// class Example + /// { + /// static void Main() + /// { + /// // data to be read + /// var data = @"Company,OpenPositions,MainTechnology,Revenue + /// Co,2,""C#, MySQL, JavaScript, HTML5 and CSS3"",500 + /// Ca,2,""C#, MySQL, JavaScript, HTML5 and CSS3"",600"; + /// + /// using(var stream = new MemoryStream(Encoding.UTF8.GetBytes(data))) + /// { + /// // create a CSV reader + /// var reader = new CsvReader(stream, false, Encoding.UTF8); + /// } + /// } + /// } + /// + /// public class CsvReader : IDisposable { private static readonly PropertyTypeCache TypeCache = new PropertyTypeCache(); diff --git a/src/Unosquare.Swan.Lite/Formatters/CsvWriter.cs b/src/Unosquare.Swan.Lite/Formatters/CsvWriter.cs index a6e438afe..303a153a3 100644 --- a/src/Unosquare.Swan.Lite/Formatters/CsvWriter.cs +++ b/src/Unosquare.Swan.Lite/Formatters/CsvWriter.cs @@ -12,6 +12,40 @@ /// /// A CSV writer useful for exporting a set of objects /// + /// + /// The following code describes how to save a list of objects into a CSV file + /// + /// using System.Collections.Generic; + /// using Unosquare.Swan.Formatters; + /// + /// class Example + /// { + /// class Person + /// { + /// public string Name { get; set; } + /// public int Age { get; set; } + /// } + /// + /// static void Main() + /// { + /// // create a list of people + /// var people = new List<Person> + /// { + /// new Person { Name = "Artyom", Age = 20 }, + /// new Person { Name = "Aloy", Age = 18 } + /// } + /// + /// // write items inside file.csv + /// CsvWriter.SaveRecords(people, "C:\\Users\\user\\Documents\\file.csv"); + /// + /// // output + /// // | Name | Age | + /// // | Artyom | 20 | + /// // | Aloy | 18 | + /// } + /// } + /// + /// public class CsvWriter : IDisposable { private static readonly PropertyTypeCache TypeCache = new PropertyTypeCache(); diff --git a/src/Unosquare.Swan.Lite/Formatters/Json.cs b/src/Unosquare.Swan.Lite/Formatters/Json.cs index db44690d4..ecc9d3d75 100644 --- a/src/Unosquare.Swan.Lite/Formatters/Json.cs +++ b/src/Unosquare.Swan.Lite/Formatters/Json.cs @@ -60,6 +60,47 @@ public static partial class Json /// A that represents the current object /// /// You need to provide an object or array + /// + /// The following example describes how to serialize a simple object + /// + /// using Unosquare.Swan.Formatters; + /// + /// class Example + /// { + /// static void Main() + /// { + /// var obj = new { One = "One", Two = "Two" }; + /// + /// var serial = Json.Serialize(obj); // {"One": "One","Two": "Two"} + /// } + /// } + /// + /// The following example details how to serialize an object using the + /// + /// using Unosquare.Swan.Attributes; + /// using Unosquare.Swan.Formatters; + /// + /// class Example + /// { + /// class JsonPropertyExample + /// { + /// [JsonProperty("data")] + /// public string Data { get; set; } + /// + /// [JsonProperty("ignoredData", true)] + /// public string IgnoredData { get; set; } + /// } + /// + /// static void Main() + /// { + /// var obj = new JsonPropertyExample() { Data = "OK", IgnoredData = "OK" }; + /// + /// // {"data": "OK"} + /// var serializedObj = Json.Serialize(obj); + /// } + /// } + /// + /// public static string Serialize( object obj, bool format = false, @@ -115,7 +156,29 @@ public static partial class Json /// if set to true it formats and indents the output. /// The include names. /// A that represents the current object - public static string SerializeOnly(object obj, bool format, params string[] includeNames) + /// + /// The following example shows how to serialize a simple object including the specified properties + /// + /// using Unosquare.Swan.Formatters; + /// + /// class Example + /// { + /// static void Main() + /// { + /// // object to serialize + /// var obj = new { One = "One", Two = "Two", Three = "Three" }; + /// + /// // the included names + /// var includedNames = new[] { "Two", "Three" }; + /// + /// // serialize only the included names + /// var data = Json.SerializeOnly(basicObject, true, includedNames); + /// // {"Two": "Two","Three": "Three" } + /// } + /// } + /// + /// + public static string SerializeOnly(object obj, bool format, params string[] includeNames) { return Serializer.Serialize(obj, 0, format, null, includeNames, null, true); } @@ -127,6 +190,29 @@ public static string SerializeOnly(object obj, bool format, params string[] incl /// if set to true it formats and indents the output. /// The exclude names. /// A that represents the current object + /// + /// The following code shows how to serialize a simple object exluding the specified properties + /// + /// using Unosquare.Swan.Formatters; + /// + /// class Example + /// { + /// static void Main() + /// { + /// // object to serialize + /// var obj = new { One = "One", Two = "Two", Three = "Three" }; + /// + /// // the excluded names + /// var excludeNames = new[] { "Two", "Three" }; + /// + /// // serialize excluding + /// var data = Json.SerializeExcluding(basicObject, false, includedNames); + /// // {"One": "One"} + /// + /// } + /// } + /// + /// public static string SerializeExcluding(object obj, bool format, params string[] excludeNames) { return Serializer.Serialize(obj, 0, format, null, null, excludeNames, false); @@ -138,6 +224,25 @@ public static string SerializeExcluding(object obj, bool format, params string[] /// /// The json. /// Type of the current deserializes + /// + /// The following code shows how to deserialize a JSON string into a Dictionary + /// + /// using Unosquare.Swan.Formatters; + /// + /// class Example + /// { + /// static void Main() + /// { + /// // json to deserialize + /// var basicJson = "{\"One\":\"One\",\"Two\":\"Two\",\"Three\":\"Three\"}"; + /// + /// // deserializes the specified json into a Dictionary<string, object>. + /// var data = Json.Deserialize(basicJson); + /// + /// } + /// } + /// + /// public static object Deserialize(string json) => Deserializer.DeserializeInternal(json); /// @@ -147,6 +252,25 @@ public static string SerializeExcluding(object obj, bool format, params string[] /// The type of object to deserialize /// The json. /// The deserialized specified type object + /// + /// The following code describes how to deserialize a JSON string into an object of type T + /// + /// using Unosquare.Swan.Formatters; + /// + /// class Example + /// { + /// static void Main() + /// { + /// // json type BasicJson to serialize + /// var basicJson = "{\"One\":\"One\",\"Two\":\"Two\",\"Three\":\"Three\"}"; + /// + /// // deserializes the specified string in a new instance of the type BasicJson. + /// var data = Json.Deserialize<BasicJson>(basicJson); + /// + /// } + /// } + /// + /// public static T Deserialize(string json) { return (T)Deserialize(json, typeof(T)); diff --git a/src/Unosquare.Swan.Lite/Terminal.cs b/src/Unosquare.Swan.Lite/Terminal.cs index dc21f0c54..e873f1713 100644 --- a/src/Unosquare.Swan.Lite/Terminal.cs +++ b/src/Unosquare.Swan.Lite/Terminal.cs @@ -6,7 +6,7 @@ namespace Unosquare.Swan using System.Threading; /// - /// A console terminal helper to create nicer output and receive input from the user + /// A console terminal helper to create nicer output and receive input from the user. /// This class is thread-safe :) /// public static partial class Terminal diff --git a/src/Unosquare.Swan/Abstractions/AppWorkerBase.cs b/src/Unosquare.Swan/Abstractions/AppWorkerBase.cs index 8a84d5796..17f180ba0 100644 --- a/src/Unosquare.Swan/Abstractions/AppWorkerBase.cs +++ b/src/Unosquare.Swan/Abstractions/AppWorkerBase.cs @@ -7,6 +7,46 @@ /// /// A base implementation of an Application service containing a worker task that performs background processing. /// + /// + /// The following code describes how to implement the class + /// + /// using System; + /// using System.Threading.Tasks; + /// using Unosquare.Swan; + /// using Unosquare.Swan.Abstractions; + /// + /// class Worker : AppWorkerBase + /// { + /// // an action that will be executed if the worker is stopped + /// public Action OnExit { get; set; } + /// + /// // override the base loop method, this is the code that'll + /// // be run once the worker is started + /// protected override void WorkerThreadLoop() + /// { + /// // while the worker hasn't been stopped + /// while (!CancellationToken.IsCancellationRequested) + /// { + /// // delay a second and then proceed + /// Task.Delay(TimeSpan.FromMilliseconds(1000), CancellationToken).Wait(); + /// + /// // just print out this + /// $"Working...".WriteLine(); + /// } + /// } + /// + /// // Once the worker is stopped this code will be executed + /// protected override void OnWorkerThreadExit() + /// { + /// // execute the base method + /// base.OnWorkerThreadExit(); + /// + /// // then if the OnExit Action is not null execute it + /// OnExit?.Invoke(); + /// } + /// } + /// + /// public abstract class AppWorkerBase : IWorker { diff --git a/src/Unosquare.Swan/Components/DelayProvider.cs b/src/Unosquare.Swan/Components/DelayProvider.cs index 0ec2040d8..3a49dbba2 100644 --- a/src/Unosquare.Swan/Components/DelayProvider.cs +++ b/src/Unosquare.Swan/Components/DelayProvider.cs @@ -9,6 +9,25 @@ /// /// Represents logic providing several delay mechanisms /// + /// + /// The following example shows how to implement delay mechanisms + /// + /// using Unosquare.Swan.Components; + /// + /// public class Example + /// { + /// public static void Main() + /// { + /// // using the ThreadSleep strategy + /// using (var delay = new DelayProvider(DelayProvider.DelayStrategy.ThreadSleep)) + /// { + /// // retrieve how much time was delayed + /// var time = delay.WaitOne(); + /// } + /// } + /// } + /// + /// public sealed class DelayProvider : IDisposable { private readonly object _syncRoot = new object(); diff --git a/src/Unosquare.Swan/Components/MessageHub.cs b/src/Unosquare.Swan/Components/MessageHub.cs index 6fe53710d..8d851072e 100644 --- a/src/Unosquare.Swan/Components/MessageHub.cs +++ b/src/Unosquare.Swan/Components/MessageHub.cs @@ -167,6 +167,45 @@ Task PublishAsync(TMessage message) #region Hub Implementation /// + /// + /// The following code describes how to use a MessageHub. Both the + /// subscription and the message sending are done in the same place but this is only for explanatory purposes. + /// + /// class Example + /// { + /// using Unosquare.Swan; + /// using Unosquare.Swan.Components; + /// + /// static void Main() + /// { + /// // using DependencyContainer to create an instance of MessageHub + /// var messageHub = DependencyContainer + /// .Current + /// .Resolve<IMessageHub>() as MessageHub; + /// + /// // create an instance of the publisher class + /// // which has a string as its content + /// var message = new MessageHubGenericMessage<string>(new object(), "SWAN"); + /// + /// // subscribe to the publisher's event + /// // and just print out the content which is a string + /// // a token is returned which can be used to unsubscribe later on + /// var token = messageHub + /// .Subscribe<MessageHubGenericMessage<string>>(m => m.Content.Info()); + /// + /// // publish the message described above which is + /// // the string 'SWAN' + /// messageHub.Publish(message); + /// + /// // unsuscribe, we will no longer receive any messages + /// messageHub.Unsubscribe<MessageHubGenericMessage<string>>(token); + /// + /// Terminal.Flush(); + /// } + /// + /// } + /// + /// public sealed class MessageHub : IMessageHub { #region Private Types and Interfaces diff --git a/src/Unosquare.Swan/Components/ProcessRunner.cs b/src/Unosquare.Swan/Components/ProcessRunner.cs index a118d9b6f..a4146e6c9 100644 --- a/src/Unosquare.Swan/Components/ProcessRunner.cs +++ b/src/Unosquare.Swan/Components/ProcessRunner.cs @@ -33,6 +33,27 @@ public static class ProcessRunner /// The arguments. /// The cancellation token. /// The type of the result produced by this Task + /// + /// The following code explains how to run an external process using the + /// method + /// + /// class Example + /// { + /// using System.Threading.Tasks; + /// using Unosquare.Swan.Components; + /// + /// static async Task Main() + /// { + /// // execute a process and save its output + /// var data = await ProcessRunner. + /// GetProcessOutputAsync("dotnet", "--help"); + /// + /// // print the output + /// data.WriteLine(); + /// } + /// } + /// + /// public static async Task GetProcessOutputAsync(string filename, string arguments = "", CancellationToken ct = default) { var result = await GetProcessResultAsync(filename, arguments, ct); @@ -48,9 +69,35 @@ public static async Task GetProcessOutputAsync(string filename, string a /// The arguments. /// The ct. /// - /// Text of the standard output and standard error streams along with the exit code + /// Text of the standard output and standard error streams along with the exit code as a instance /// /// filename + /// + /// The following code describes how to run an external process using the method. + /// + /// class Example + /// { + /// using System.Threading.Tasks; + /// using Unosquare.Swan.Components; + /// + /// static async Task Main() + /// { + /// // Execute a process asynchronously + /// var data = await ProcessRunner + /// .GetProcessResultAsync("dotnet", "--help"); + /// + /// // print out the exit code + /// $"{data.ExitCode}".WriteLine(); + /// + /// // print out the output + /// data.StandardOutput.WriteLine(); + /// + /// // and the error if exists + /// data.StandardError.Error(); + /// } + /// } + /// + /// public static async Task GetProcessResultAsync(string filename, string arguments = "", CancellationToken ct = default) { if (filename == null) @@ -84,6 +131,35 @@ public static async Task GetProcessResultAsync(string filename, s /// if set to true the next data callback will wait until the current one completes. /// The ct. /// Value type will be -1 for forceful termination of the process + /// + /// The following example illustrates how to run an external process using the + /// + /// method + /// + /// class Example + /// { + /// using System.Diagnostics; + /// using System.Text; + /// using System.Threading.Tasks; + /// using Unosquare.Swan; + /// using Unosquare.Swan.Components; + /// + /// static async Task Main() + /// { + /// // Execute a process asynchronously + /// var data = await ProcessRunner + /// .RunProcessAsync("dotnet", "--help", Print, Print); + /// + /// // flush all messages + /// Terminal.Flush(); + /// } + /// + /// // a callback to print both output or errors + /// static void Print(byte[] data, Process proc) => + /// Encoding.GetEncoding(0).GetString(data).WriteLine(); + /// } + /// + /// public static Task RunProcessAsync(string filename, string arguments, ProcessDataReceivedCallback onOutputData, ProcessDataReceivedCallback onErrorData, bool syncEvents = true, CancellationToken ct = default) { if (filename == null) diff --git a/src/Unosquare.Swan/Networking/Connection.cs b/src/Unosquare.Swan/Networking/Connection.cs index 9eed6e11b..bf63773fb 100644 --- a/src/Unosquare.Swan/Networking/Connection.cs +++ b/src/Unosquare.Swan/Networking/Connection.cs @@ -23,6 +23,60 @@ namespace Unosquare.Swan.Networking /// Manual Reading Mode: Data reception events are NEVER fired. No background threads are used. Use Read methods to receive data /// /// + /// + /// The following code explains how to create a TCP server + /// + /// using System.Text; + /// using Unosquare.Swan.Networking; + /// + /// class Example + /// { + /// static void Main() + /// { + /// // create a new connection listener on a specific port + /// var connectionListener = new ConnectionListener(1337); + /// + /// // handle the OnConnectionAccepting event + /// connectionListener.OnConnectionAccepted += (s, e) => + /// { + /// // create a new connection + /// using (var con = new Connection(e.Client)) + /// { + /// con.WriteLineAsync("Hello world!").Wait(); + /// } + /// }; + /// + /// connectionListener.Start(); + /// } + /// } + /// + /// The following code describes how to create a TCP client + /// + /// using System.Net.Sockets; + /// using System.Text; + /// using System.Threading.Tasks; + /// using Unosquare.Swan.Networking; + /// + /// class Example + /// { + /// static async Task Main() + /// { + /// // create a new TcpCLient object + /// var client = new TcpClient(); + /// + /// // connect to a specific address and port + /// client.Connect("localhost", 1337); + /// + /// //create a new connection with specific encoding, + /// //new line sequence and continous reading disabled + /// using (var cn = new Connection(client, Encoding.UTF8, "\r\n", true, 0)) + /// { + /// var response = await cn.ReadTextAsync(); + /// } + /// } + /// } + /// + /// public sealed class Connection : IDisposable { // New Line definitions for reading. This applies to both, events and read methods diff --git a/src/Unosquare.Swan/Networking/Ldap/LdapConnection.cs b/src/Unosquare.Swan/Networking/Ldap/LdapConnection.cs index 8ed05b81b..2adf802fa 100644 --- a/src/Unosquare.Swan/Networking/Ldap/LdapConnection.cs +++ b/src/Unosquare.Swan/Networking/Ldap/LdapConnection.cs @@ -25,8 +25,76 @@ namespace Unosquare.Swan.Networking.Ldap /// application may have more than one LdapConnection object, connected /// to the same or different directory servers. /// - /// Base on https://github.com/dsbenghe/Novell.Directory.Ldap.NETStandard + /// Based on https://github.com/dsbenghe/Novell.Directory.Ldap.NETStandard /// + /// + /// The following code describes how to use the LdapConnection class + /// + /// class Example + /// { + /// using Unosquare.Swan; + /// using Unosquare.Swan.Networking.Ldap; + /// using System.Threading.Tasks; + /// + /// static async Task Main() + /// { + /// // create a LdapConnection object + /// var connection = new LdapConnection(); + /// + /// // connect to a server + /// await connection.Connect("ldap.forumsys.com", 389); + /// + /// // set up the credentials + /// await connection.Bind("cn=read-only-admin,dc=example,dc=com", "password"); + /// + /// // retrieve all entries that have the specified email using ScopeSub + /// // which searches all entries at all levels under + /// // and including the specified base DN + /// var searchResult = await connection + /// .Search("dc=example,dc=com", LdapConnection.ScopeSub, "(cn=Isaac Newton)"); + /// + /// // if there are more entries remaining keep going + /// while (searchResult.HasMore()) + /// { + /// // point to the next entry + /// var entry = searchResult.Next(); + /// + /// // get all attributes + /// var entryAttributes = entry.GetAttributeSet(); + /// + /// // select its name and print it out + /// entryAttributes.GetAttribute("cn").StringValue.Info(); + /// } + /// + /// // modify Tesla and sets its email as tesla@email.com + /// connection.Modify("uid=tesla,dc=example,dc=com", + /// new[] { + /// new LdapModification(LdapModificationOp.Replace, + /// "mail", "tesla@email.com") + /// }); + /// + /// // delete the listed values from the given attribute + /// connection.Modify("uid=tesla,dc=example,dc=com", + /// new[] { + /// new LdapModification(LdapModificationOp.Delete, + /// "mail", "tesla@email.com") + /// }); + /// + /// // add back the recently deleted property + /// connection.Modify("uid=tesla,dc=example,dc=com", + /// new[] { + /// new LdapModification(LdapModificationOp.Add, + /// "mail", "tesla@email.com") + /// }); + /// + /// // disconnect from the LDAP server + /// connection.Disconnect(); + /// + /// Terminal.Flush(); + /// } + /// } + /// + /// public class LdapConnection { /// diff --git a/src/Unosquare.Swan/Networking/SmtpClient.cs b/src/Unosquare.Swan/Networking/SmtpClient.cs index b85da471d..17ec2913e 100644 --- a/src/Unosquare.Swan/Networking/SmtpClient.cs +++ b/src/Unosquare.Swan/Networking/SmtpClient.cs @@ -19,6 +19,80 @@ namespace Unosquare.Swan.Networking /// /// Represents a basic SMTP client that is capable of submitting messages to an SMTP server. /// + /// + /// The following code explains how to send a simple e-mail + /// + /// using System.Net.Mail; + /// + /// class Example + /// { + /// static void Main() + /// { + /// // create a new smtp client using google's smtp server + /// var client = new SmtpClient("smtp.gmail.com", 587); + /// + /// // send an email + /// client.SendMailAsync( + /// new MailMessage("sender@test.com", "recipient@test.cm", "Subject", "Body")); + /// } + /// } + /// + /// The following code demonstrates how to sent an e-mail using a SmtpSessionState + /// + /// using System.Net.Mail; + /// + /// class Example + /// { + /// static void Main() + /// { + /// // create a new smtp client using google's smtp server + /// var client = new SmtpClient("smtp.gmail.com", 587); + /// + /// // create a new session state with a sender address + /// var session = new SmtpSessionState { SenderAddress = "sender@test.com" }; + /// + /// // add a recipient + /// session.Recipients.Add("recipient@test.cm"); + /// + /// // send + /// client.SendMailAsync(session); + /// } + /// } + /// + /// The following code shows how to send an e-mail with an attachment + /// + /// using System.Net.Mail; + /// + /// class Example + /// { + /// static void Main() + /// { + /// // create a new smtp client using google's smtp server + /// var client = new SmtpClient("smtp.gmail.com", 587); + /// + /// // create a new session state with a sender address + /// var session = new SmtpSessionState { SenderAddress = "sender@test.com" }; + /// + /// // add a recipient + /// session.Recipients.Add("recipient@test.cm"); + /// + /// // load a file as an attachment + /// var attachment = new MimePart("image", "gif") + /// { + /// Content = new + /// MimeContent(File.OpenRead("meme.gif"), ContentEncoding.Default), + /// ContentDisposition = + /// new ContentDisposition(ContentDisposition.Attachment), + /// ContentTransferEncoding = ContentEncoding.Base64, + /// FileName = Path.GetFileName("meme.gif") + /// }; + /// + /// // send + /// client.SendMailAsync(session); + /// } + /// } + /// + /// public class SmtpClient { /// diff --git a/test/Unosquare.Swan.Test/DelayProviderTest.cs b/test/Unosquare.Swan.Test/DelayProviderTest.cs index c80ee4c0e..8b8743d08 100644 --- a/test/Unosquare.Swan.Test/DelayProviderTest.cs +++ b/test/Unosquare.Swan.Test/DelayProviderTest.cs @@ -1,7 +1,7 @@ namespace Unosquare.Swan.Test { using NUnit.Framework; - using Components; + using Unosquare.Swan.Components; [TestFixture] public class DelayProviderTest