GithubHelp home page GithubHelp logo

bryanwilhite / songhaycore Goto Github PK

View Code? Open in Web Editor NEW
1.0 2.0 0.0 49.64 MB

core reusable, opinionated concerns for *all* 🧐 of my C# projects

Home Page: http://songhayblog.azurewebsites.net/

License: MIT License

C# 100.00%
csharp c-sharp linq newtonsoft-json nuget-packages xunit tavis mstestv2

songhaycore's Introduction

SonghayCore

Build Status

The Core code to install as a NuGet package for all of my studio Solutions. Anyone who may be reading this 👀 is free to do the same. This package is based on a project file that supports multi-targeting, declaring support for net6.0.

NuGet package 📦: SonghayCore

documentation 📚: SonghayCore API

coverlet test coverage 🔬☔: [report]

version 6.0 changes

The dominant theme in version 6.0 is about adopting .NET 6.0. The GitHub project for this release has the most documented details. Many version 6.0 changes are breaking changes.

Notable changes:

  • Issue #131 was about removing direct support for WPF and any members marked obsolete in previous releases.
  • Issue #135 was about separating Newtonsoft JSON routines from the Core.
  • Issue #137 was about recognizing the new nullability features of .NET.
  • Issue #140 was about finally adding coverlet code coverage.

core reusable, opinionated concerns

Songhay.Diagnostics

This Core is exclusively concerned with tracing. Logging concerns should be logically above this Core. TraceSources and TraceSourceExtensions define how tracing should be implemented with a bias toward using all source levels. When tracing is not configured for this Core then it will be ignored without throwing exceptions.

For a review of the organizational difference between tracing and logging, see “Tracing vs Logging vs Monitoring: What’s the Difference?” by Chrissy Kidd.

Documentation 📚: Songhay.Diagnostics

Songhay.Extensions

The Songhay System uses imperative C# code with a view to make it more functional in an effort to control complexity and enhance maintainability.

The preference for extension methods encourages stateless, reusable routines (many of them are “pure” functions).

Notable extensions:

There is support for URI templates (to be used with RestApiMetadata) in the form of extension methods, running on top of Tavis.UriTemplates.

Documentation 📚: Songhay.Extensions

Songhay.Models

The Core models of the Songhay System define types for MIME, XHTML, OPML, REST, the Repository, the Display Item (for WPF and other MVVM solutions), etc.

The Core models are “anemic” by design (there are very few abstract classes)—any logic would be found first in an Extension Method.

Notable models:

Documentation 📚: Songhay.Models

Songhay.Xml

The “core” of the Core is concern for XML. The Songhay System started out as utilities around XPathDocument and grew into LINQ for XML—over XDocument.

Documentation 📚: Songhay.Xml

satellite packages

SonghayCore.xUnit

Defines reusable class definitions for xUnit. Featured is the ProjectFileDataAttribute, allowing test data files to be loaded from a relative path.

NuGet package 📦: SonghayCore.xUnit

Documentation 📚: Songhay.Tests

SonghayCore.Newtonsoft

Core reusable, opinionated Newtonsoft concerns for my C# projects.

GitHub repo: https://github.com/BryanWilhite/SonghayCore.Newtonsoft

NuGet package 📦: SonghayCore.Newtonsoft

Studio packages dependent on SonghayCore

graph BT
    netstandard2[.NET Standard 2.0]
    net6[.NET 6.0]

    1[`SonghayCore`]
    2[`SonghayCore.Newtonsoft`]

    net6-->1
    netstandard2-->2
    2-..->|optional addition|1

    1-->3[`SonghayCore.xUnit`]
    1-->4[`Songhay.DataAccess`]
    1-->5[`Songhay.Feeds`]
    1-->6[`Songhay.Publications`]
    1-->7[`Songhay.Social`]

@BryanWilhite

songhaycore's People

Contributors

bryanwilhite avatar

Stargazers

 avatar

Watchers

 avatar  avatar

songhaycore's Issues

Add Tavis.UriTemplates support to core

The System.ServiceModel.Primitives NuGet package gives us Microsoft’s version of UriTemplate with its very useful BindByPosition() method. Now, we can install this package in a .NET Core project but (from my experience) UriTemplate is unavailable. A robust (and standards-based) alternative is Tavis.UriTemplates [GitHub]. This works fine on .NET Core.

However, that useful BindByPosition() method is not there and as of this writing the repo activity is kind of low. Since I am too lazy (busy) to formally fork this repo, I suggest that a separate NuGet package be built (Songhay.UriTemplates) based on Tavis.UriTemplates. I can then throw in my extension methods for BindByPosition().

Add Songhay.Framework.Core project and package

a project called Songhay.Framework.Core intends to centralize all the non-.NET-Core/Standard features the Studio intends to support:

  • ObservableSortingCollection, RefreshEventArgs.cs, SortableCollectionView currently under 4.6.1
  • abandon BackgroundWorkerUtility and BackgroundWorkerUtilityData
  • roll-up ConfigurationManagerExtensions, DataServiceCollectionExtensions ❓, EncryptionMetadataExtensions.ConnectionStringSettings, ICommunicationObjectExtensions, RestApiMetadataExtensions.ServiceModel ❓, TraceSourcesExtensions.ConfigurationManager
  • roll-up ISyndicatable
  • roll-up BasicHttpBinaryBinding
  • roll-up FrameworkUtility.Process
  • roll-up Songhay.Net.HttpWebRequest

move helpers to Core

from WordpressExportTests:

/// <summary>
/// Converts the specified local time to UTC.
/// </summary>
/// <param name="local">The local <see cref="DateTime"/></param>
/// <returns></returns>
public static string ConvertLocalToUtc(DateTime local)
{ //TODO: move to SonghayCore
    return local
        .ToUniversalTime()
        .ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
}
/// <summary>
/// Get the CDATA value from the specified node.
/// </summary>
/// <param name="node">The <see cref="XNode"/></param>
public static string GetCDataValue(XNode node)
{ //TODO: move to SonghayCore
    var cData = node as XCData;
    return cData?.Value;
}

`namespace SonghayCore` has leaked into codebase

enforce the convention namespace Songhay instead of namespace SonghayCore

do not use EnsureTraceSource in Core

null check for TraceSource is missing:

var message = string.Format("{0}\n{1}", ex.Message, ex.StackTrace);

this lack of a null check is probably why EnsureTraceSource is used in Core

WithTraceSource should be changed to WithSourceLevels:

public static TraceSource WithTraceSource(this TraceSource traceSource, SourceLevels level)

WriteLine overloads should be marked obsolete and replaced with ?TraceInformation:

public static void WriteLine(this TraceSource traceSource, string message)

GetTraceSource should return null instead of a default source which would effectively shut off tracing:

public TraceSource GetTraceSource(string name)

🔥 change WithAllSourceLevels to WithSourceLevels

the use of WithAllSourceLevels in Core is an opinionated statement, effectively saying that tracing should turn on the fire hose without any options for granularity; a new issue should be generated to explore this opinion🚧

the GetConfiguredTraceSource pattern should be identical for .NET Framework and .NET Standard:

public static TraceSource GetConfiguredTraceSource(this TraceSources instance)

start here: https://github.com/BryanWilhite/Songhay.HelloWorlds.Activities/blob/master/Songhay.HelloWorlds.Shell/Program.cs#L29

🔥 remove TraceSourceExtensions.TraceData because they are identical to TraceSource.TraceData; use TraceSource?.TraceData instead

🔥 remove TraceSourceExtensions.TraceTransfer because it is identical to TraceSource.TraceTransfer; use TraceSource?.TraceTransfer instead

💡 this issue exists because of the decision (today) that the Core should be concerned with tracing instead of logging; continued Core investment in TraceSource is effectively saying that one is free to use logging (e.g. ILogger) above the Core and the option is there to capture TraceSource writes as well

https://www.bmc.com/blogs/monitoring-logging-tracing/

consider adding `System.Net.WebUtility` decoding to fluent string extensions

from WordpressExportTests:

public static string GetBlogSlug(string name)
{
    // ref:📚 https://www.w3schools.com/tags/ref_urlencode.asp
    string RemoveEncodedSpecialCharacters(string s)
    {
        return s
            .Replace("%e2%80%a6", string.Empty) // …
            .Replace("%e2%80%98", string.Empty) // ‘
            .Replace("%e2%80%99", string.Empty) // ’
            .Replace("%e2%80%9c", string.Empty) // “
            .Replace("%e2%80%9d", string.Empty) // ”
            .Replace("%e2%80%a2", string.Empty) // •
            .Replace("%c2%a9", string.Empty) // ©
            .Replace("%c2%ae", string.Empty) // ®
        ;
    }
    var slug = WebUtility
        .HtmlDecode(RemoveEncodedSpecialCharacters(name))
        .ToBlogSlug();
    return slug;
}

BTW: WebUtility is everywhere 📖 https://docs.microsoft.com/en-us/dotnet/api/system.net.webutility?view=netstandard-2.1

consider adding a ToCollection() extension method

IEnumerable vs ICollection vs IList vs IQueryable in C#” reminds me that ICollection usage should be ‘promoted’ in SonghayCore

  • exposing ICollection from web APIs should provide a static Count property value for endpoint consumers (usually reading JSON)
  • the IsReadOnly property is a clear expression of developer intent

ICollection has been recommended for years as the formal way of exposing an API (web or not) across layers; the SonghayCore does not reflect this guidance

questions to explore

  • why is there no ToCollection() method in MoreLinq? —too obvious?
  • is this ToCollection() method sufficient?

Add formal command-line args support to IActivity pattern

Now that we have pushed back command-line support to the Activity level, a new contract, say, IActivityArgs, will indicate that an Activity supports command-line arguments. This would be discoverable through reflection.

All args could hydrate into Dictionary<string, string> from JSON or --key value pairs which would allow standardizing parsing and displaying help. This implies that:

public interface IActivityArgs
{
    Dictionary<string, string> Parse(string[] args);

    string DisplayHelp(IEnumerable<string> keys);
}

...where keys refers to the keys of Dictionary<string, string>. These keys will map to an internal dictionary with the help text.

reevaluate the `TraceSource`-based logging pattern

using the ILogger interface does not solve the problem of establishing conventions around instantiation of a logger—on the contrary: it forces the establishment of conventions around the use of IoC containers

BTW: the TraceSourceLogger class is marked obsolete to be replaced by TraceSourceLoggerProvider [docs] even though it is used internally 👀😬

and why is all of this work still under ASP.NET? …this could be considered a signal from Microsoft that logging is not to be considered a .NET standard

add `FileInfoExtensions` for System.IO.Compression extension methods

The FileSystemInfo class contains methods that are common to file and directory manipulation. A FileSystemInfo object can represent either a file or a directory, thus serving as the basis for FileInfo or DirectoryInfo objects. Use this base class when parsing a lot of files and directories. [docs]

  • add FrameworkFileUtility.Compression partial class
  • migrate TestContextExtensions.ZipArchive.cs [src] members to FileInfoExtensions
  • add sorting options to ShouldReadZipArchiveEntries* members
  • re-factor DirectoryInfoExtensions.ToCombinedPath [src] to be based on FileSystemInfoExtensions.ToCombinedPath

add JTokenExtensions

to avoid casting JToken to JObject:

var uri = (j["input"] as JObject).GetJToken("uri", throwException: true).Value<string>();

start with something like this (without the xunit stuff):

public static class JTokenExtensions
{
    public static TValue GetValue<TValue>(this JToken jToken, bool assertValueNotNull = true)
    {
        Assert.NotNull(jToken);
        var value = jToken.Value<TValue>();
        if (assertValueNotNull) Assert.NotNull(value);
        return value;
    }
}

public static class JObjectExtensions
{
    public static JObject GetJObject(this JObject jObject, string propertyName)
    {
        if (jObject == null) throw new NullReferenceException("The expected file configuration data is not here.");
        var value = jObject[propertyName]?.Value<JObject>();
        Assert.NotNull(value);
        return value;
    }

    public static TValue GetValue<TValue>(this JObject jObject, string propertyName)
    {
        if (jObject == null) throw new NullReferenceException("The expected file configuration data is not here.");
        var value = jObject[propertyName].GetValue<TValue>();
        Assert.NotNull(value);
        return value;
    }
}

what is the difference between `StringExtensions.Reduce` and `StringExtensions.Truncate`?

This is the Reduce algorithm from Tomas Kubes:

public static string Reduce(this string s, int count, string endings)
{
    if (count < endings.Length) throw new Exception("Failed to reduce to less then endings length.");

    int sLength = s.Length;
    int len = sLength;
    if (endings != null) len += endings.Length;

    if (count > sLength) return s; //it's too short to reduce

    s = s.Substring(0, sLength - len + count);

    if (endings != null) s += endings;

    return s;
}

My Truncate:

public static string Truncate(this string input, int length, string ellipsis)
{
    if (string.IsNullOrEmpty(input)) return input;
    if (input.Length <= length) return input;
    return string.Concat(input.Substring(0, length).TrimEnd(), ellipsis);
}

Drop .NET 4.51 Support?

I need to re-justify why SonghayCore supports .NET 4.5.1. This may have come about solely because of day-job drama.

SonghayCore-netstandard2.0.Tests project needed

It feels like there should be a bias toward testing everything in .NET Standard 2.0 going forward. The only reason for not doing this would be for types that are not supported. This move would be first move toward making the Core cross-platform-first.

reduce concerns for cloning instances in the Core

my naïve attempts to provide cloning should be reduced

maintainers of, say, DeepCloner, inform me:

If your code is on very limited permission set, you can try to use another library, e.g. CloneExtensions. It clones only public properties of objects, so, result can differ, but should work better (it requires only RestrictedMemberAccess permission).

the maintainers of CloneExtensions inform me that they are using Expression trees to clone which immediately tells me to stop pretending i know what i am doing

consider modernizing Regex patterns

the Regex patterns used for BryanWilhite/Songhay.Blog#43 take advantage of lambda expressions which is a C# 3.0 feature and the usage of Regex in SonghayCore should require 2.0 backwards compatibility

the code should be reviewed to look for modernization/simplification/clarity/maintainability opportunities while still (sadly) supporting this backwards compatilibility

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.