­­Coding Faster With The dotNetTips Utility - February 2021 Update

My goal is to release quarterly updates to my NuGet packages and source code. This updateincludes over 25 new methods and types along with more unit testing and more benchmark tests. Below, I have documented some of the new methods along with a new type and some older methods too.

Logging Application Information

 
Recently while working on an API written with ASP.NET Core, I wanted to make it easy to log application information to the log when the site starts up. I added a new method called
LoggingHelper.LogApplicationInformation(). Here is how to use it,
  1. LoggingHelper.LogApplicationInformation(logger);  
Here is an example of what it logs,
 
AppInfo:Company – dotNetTips.com
AppInfo:Version - 16.8.0
AppInfo:Copyright - © dotNetTips.com.All rights reserved.
AppInfo:Product - dotNetTips.Spargine
AppInfo:FileVersion - 15.0.0
AppInfo:Title - dotNetTips.Spargine.
 
Unfortunately, if you use a logger framework like Serilog, this method will not work since their logger does not support the ILogger interface. I hope they fix this.
 

Logging Computer Information

 
Working with the same API, I wanted to make it easy to log computer information during startup to make it easier to know what the production computer information. I added a new method called LoggingHelper.
 
LogComputerInformation(). Here is how to use it,
  1. LoggingHelper.LogComputerInformation(logger);  
Here is an example of what it logs from my Microsoft Surface,
 
AppInfo:ComputerCulture - eng
AppInfo:ComputerUICulture - eng
AppInfo:CurrentManagedTreadId - 6
AppInfo:CurrentSystemTickCount - 185990421
AppInfo:CurrentWorkingDirectory - C:\\Spargine
AppInfo:FrameworkDescription - .NET Core 3.1.10
AppInfo:FrameworkVersion - 3.1.10
AppInfo:HasShutdownStarted - False
AppInfo:IPAddress - 999.168.0.7
AppInfo:Is64BitOperatingSystem - True
AppInfo:IsUserInteractive - True
AppInfo:MachineName - DOTNETTIPS
AppInfo:OSArchitecture - X64
AppInfo:OSDescription - Microsoft Windows 10.0.19042
AppInfo:OsMemoryPageSize - 4096
AppInfo:PhysicalMemoryInUse - 49123328
AppInfo:ProcessorCount - 4
AppInfo:SystemDirectory - C:\\WINDOWS\\system32
AppInfo:UserDomainName - DOTNETTIPS
AppInfo:UserName - dotNetDave
 

Retrieving Property Names & Values

 
If you need to retrieve property names and values from a type, I created a method called TypeHelper.GetPropertyValues<T>(). This makes it easy to log the state of an object. Here is how to use it,
  1. var result = TypeHelper.GetPropertyValues(person);  
Here is an example of the output,
 
[Address1, `fqrZjAqTNANUNIyJWFyNjCQx]
[Address2, bSUnkmaIIMutgJtAKYZANpSHM]
[Age, 25]
[BornOn, 1231957 2:45:24 PM -08:00]
[CellPhone, 704-375-5873]
[City, fDbZYFMANE\MLxD]
[Country, RbPjkyMasw`gnWR]
[FirstName, ugdv\bhaHgSY^Ui]
[HomePhone, 147-205-1085]
[Id, f1bcbdbdf18a4adaa89e46383b235008]
[LastName, H^hkKhwWggIrUCYbbxiFEJGJM]
[PostalCode, 86560656]
 

Converting a Dictionary to a Delimited String

 
I added a new extension method that works with IDictionarycalled ToDelimitedString() that converts it to a delimited string. Here is how to use it,
  1. var result = (collection as IDictionary).ToDelimitedString(',');  
Here is an example of the output,
 
pfCfZQFGPWYXBlUv: pfCfZQFGPWYXBlUvVHNb]ZjBO_LTbQBSCYb,
Dnadh[d`FP^SjNeCV: Dnadh[d`FP^SjNeChCvVuBXuEl^yVFUbKXsaacsCpJuxAscU
 

Converting Object Properties to a Dictionary

 
If you want to convert all the properties in an object to a Dictionary, that can be done with the new extension method called PropertiesToDictionary(). This method returns the full property name as the key and converts the value to a string. Here is an example on how to use it.
  1. var personProper = RandomData.GeneratePersonCollection(1).First();  
  2. var result = personProper.PropertiesToDictionary(  
  3. memberName: $"Person-{personProper.Id}", ignoreNulls: true);  
The output from an object called PersonRecord, looks like this.
 
PersonRecord,
PersonRecord.BornOn:1/29/2007 11:52:12 AM -08:00,
PersonRecord.CellPhone:747-388-4458,
PersonRecord.Email:[email protected],
PersonRecord.FirstName:ZyeMgwQRFABsisq,
PersonRecord.HomePhone:255-871-4415,
PersonRecord.Id:58dc933fe6004719a37e7a35373ad645,
PersonRecord.LastName:jiqWAGoOeKTpjWhojFyRHld,
PersonRecord.Addresses[0].Address1:XkbOcAlseMEMnPYjkEcYWnFD,
PersonRecord.Addresses[0].Address2:tJkpTHikrRfFaGENXagaw,
PersonRecord.Addresses[0].City:KlWAAwKhqADREVuwmXJeAU,
PersonRecord.Addresses[0].Country:AtNNbnUIVSjUQicVXNMULJ,
PersonRecord.Addresses[0].Id:9330f3a225b14d96b67779f2c932302a,
PersonRecord.Addresses[0].CountyProvince:EkdKDBGWfGiviOMhIh,
PersonRecord.Addresses[0].State:RGOuDpJyfgwxyfC,
PersonRecord.Addresses[0].Phone:065 - 507 - 7161,
PersonRecord.Addresses[0].PostalCode:56633485,
PersonRecord.Addresses[1].Address1:lGSJwGNOtdrXvRxPcVCZHhk,
PersonRecord.Addresses[1].Address2:EJGOmHyfAPERADrTRxlDFU,
PersonRecord.Addresses[1].City:xiWPASydYBEHfpVrluPNgOFS,
PersonRecord.Addresses[1].Country:JFpIljBDlQEkiehQrxjhJ,
PersonRecord.Addresses[1].Id:8c95fd0cbbcf4beb993081bdd9c96ceb,
PersonRecord.Addresses[1].CountyProvince:FyHoHRZQwpMJgjABVUk,
PersonRecord.Addresses[1].State:dxeZknHyLowUS,
PersonRecord.Addresses[1].Phone:511 - 286 - 7653,
PersonRecord.Addresses[1].PostalCode:33385672
 

Converting Object Property Values to a String

 
Recently, where I work, they came to me and said that whenever certain data is changed, they want to record that change into a custom data type in Salesforce. To make this easy, I created a new object extension method called PropertiesToString(). It even works for objects with nested objects too.
 
Here is how I test it in the unit test project.
  1. var personRecord = RandomData.GeneratePersonCollection(1).First();  
  2. var result = personRecord.PropertiesToString(  
  3. header: "PersonRecord", keyValueSeparator:':',  
  4. sequenceSeparator: ", ", ignoreNulls: true);  
Here is an example of the output from an object that has a nested object.
 
Addresses:
Address1: hWFJD]]WQKlhQWriKIT]PIXMw,
Address2: jsDipU]uudxBBKAisIOHBbuTs,
City: UJJCr_ysMTdZgZoPmVltgJwTn,
Country: VyIEvHxjo\\LTrCExInqWPMiYr,
CountyProvince: NMIYLLLoO]`poQLejqxd,
Id: be8e69b0bd324650a0a163924249fd5c,
Phone: 882-684-3084, PostalCode: 12616872,
State: cQy^c`_IT]fk`Uj,
Address1: ovSt[^gpFrjSOGccQoYNgdXQl,
Address2: ImKqZMxn`tOUAUlv[tfsMQBjt,
City: UuGGCK_CHSk]xefk_hMUNP[gR,
Country: MjkX`rk[wEQrg]jiSsCBZ\\OAH,
CountyProvince: hbnVfF[Zop[nda[yBB`U,
Id: ebf0de3374ba4916b1a56efe9c76e5f0,
Phone: 771-458-3357, PostalCode: 64627280,
State: RyoYrgOuhSbCX[h,
BornOn: 1/27/1988 8:48:31 AM -08:00, CellPhone: 682-154-2441,
Email: [email protected], FirstName: ujUPhQNMphikhfq, HomePhone: 613-627-3376,Id: 228ef3100991488297246a1c3fe65664,
LastName: `cqGfdLORVgA\\DRUHLO^LPZYt
 

Returning a Formatted String from DateTime

 
Recently, someone on Twitter posted a tweet complaining about they cannot remember all the different formatting strings for the DateTime and DateTimeOffset types. Later that day I created an extension method called ToFormattedString(). I tried to capture all the different formatting strings along with a few custom ones.
 
Here is how to use it,
  1. var retult = DateTime.Now.ToFormattedString(DateTimeFormat.FullDateLongTime);  
There are 16 available formatting settings included with DateTimeFormat. Here is an example of all of them,
 
FullDateLongTime: Thursday, January 7, 2021 3:36:39 PM
FullDateShortTime: Thursday, January 7, 2021 3:36 PM
FullDateTime: Thursday, January 7, 2021 3:36 PM
GeneralDateLongTime: 1/7/2021 3:36:39 PM
GeneralDateShortTime: 1/7/2021 3:36 PM
Jan01Comma2020: Jan 07, 2021
Janurary01Comma2020: January 07, 2021
LongDate: Thursday, January 7, 2021
LongTime: 3:36:39 PM
MonthDay: January 7
MonthYear: January 2021
RFC1123: Thu, 07 Jan 2021 15:36:39 GMT
RoundTripDateTime: 2021-01-07T15:36:39.4416894-08:00
ShortDate: 1/7/2021
ShortTime: 3:36 PM
SortableDateTime: 2021-01-07T15:36:39
UniversalFullDateTime: Thursday, January 7, 2021 11:36:39 PM
 

Returning a Formatted String from Number

 
I also did the same thing I did for formatting DateTime, but for numbers. Again, it is called ToFormattedString() and supports the int, double, long, ulong, uint, short and ushort. Here is how to use it,
  1. var result = testValue.ToFormattedString(NumericFormat.Currency);  
This method supports the following formatting: Currency, Decimal, Exponential, FixedPoint, General, Hexadecimal, Number, Percent and RoundTrip. Here is an example of the output for short,
 
Currency: $32,767.00
Decimal: 32767
Exponential: 3.276700E+004
FixedPoint: 32767.00
General: 32767,
Hexadecimal: 7FFF,
Number: 32,767.00
Percent: 3,276,700.00%
 

Creating an Enumeration Without Using Enum

 
I have always liked the enum type in programming since it allowed us to get rid of “magic numbers”. But what if you want to do the same thing but with other value types? As far as I am aware, there is not an easy way to do that in .NET. I have run into this countless times writing .NET code. When I went to work on the two ToFormattedString() methods discussed above, I ran into this issue again since my values needed to be strings to hold the formatting strings. I went to search for how others solved this issue, and I ran across code the Jimmy Bogard wrote that seemed like it would do the trick.
 
Jimmy created an abstract class called Enumeration. I inherited it and created the DateTypeFormat and NumericFormat enumerations. Here is an example of what the DateTypeFormat type looks like,
  1. public class DateTimeFormat : Enumeration  
  2. {  
  3.     public static readonlyDateTimeFormatFullDateLongTime = new DateTimeFormat(0, "F");  
  4.   
  5.     public static readonlyDateTimeFormatFullDateShortTime = new DateTimeFormat(1, "f");  
  6.   
  7.     private DateTimeFormat()  
  8.     {}  
  9.   
  10.     private DateTimeFormat(int value, string displayName)  
  11.         : base(value, displayName)  
  12.     {}  
  13. }  
Here is the ToFormattedString() method looks like for the DateTime type,
  1. public static string ToFormattedString(this DateTime input, DateTimeFormat format)  
  2. {  
  3.     if (format == null)  
  4.     {  
  5.     ExceptionThrower.ThrowArgumentNullException(nameof(format));  
  6.     }  
  7.   
  8.     return input.ToString(format.DisplayName, CultureInfo.CurrentCulture);  
  9. }  

Summary

 
I hope you will check out these methods or any of the others in the assemblies.Stay tuned to this site for upcoming news about my new .NET 5 open-source assemblies and NuGet packages!
 
If you have any comments or suggestions, please comment below.I am always looking for new things for these open-source projects!


McCarter Consulting
Software architecture, code & app performance, code quality, Microsoft .NET & mentoring. Available!