Skip to content
Functional framework to compose functions parametrized by object navigation expression (such functions as "clone", "compare", "serialize" etc.) and provide some popular but missed in standard framework abstractions.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
AdminkaV1
BenchmarkDotNet.Artifacts/results
Routines.ActiveDirectory
Routines.AspNetCore
Routines.Configuration.Classic
Routines.Configuration.Standard
Routines.Storage.Ef6
Routines.Storage.EfCore.Relational.SqlServer
Routines.Storage.EfCore.Relational
Routines.Storage.EfCore
Routines.Storage.SqlServer
Routines
Tests
Tour
.editorconfig
.gitattributes
.gitignore
Article.txt
Benchmark.ps1
BenchmarkAdminka.ps1
BenchmarkClassic.ps1
BenchmarkWindows.ps1
CHANGELOG.md
LICENSE
OpenCover.ps1
README.md
Routines.png
Routines.sln
VS Configuration.txt
github log.txt
nugetall.ps1

README.md

Routines

Fixing abstractions

Functional framework to compose functions parametrized by object navigation expression (such functions as "clone", "compare", "serialize" etc.) and provide some popular but missed in standard framework abstractions.

It is based on DSL Include idea:

Serialization to JSON:

var formatter = JsonManager.ComposeFormatter<Point>(   // or ComposeEnumerableFormatter
   chain=>chain   
      // DSL Includes
      .Include(e=>e.X)  // leaf
      .Include(e=>e.Y)  // leaf 
           .TnenInclude(e=>e.NextPoint) // navigation node
              .TnenIncluding(e=>e.X) // node
              .TnenIncluding(e=>e.Y) // node
); // save it to reuse
var json = formatter2(new Point{X=1,Y=-1});

More options:

var formatter = JsonManager.ComposeEnumerableFormatter(include
                    , rootHandleNullArray: false // root null or empty
                    , handleNullProperty: false  // include properties that are null
                    , handleNullArrayProperty: false  // include array properties that are null
                    , useToString: true // if there are not default formatter 
                    , useToString: false,
                    , dateTimeFormat: "YYYYMMDD", 
                    , floatingPointFormat: "M4"
            );

More options SubTree:

var formatter2 = JsonManager.ComposeFormatter(
                include,
                rules => rules
                    .SubTree(
                          chain => chain.Include(e => e.Text2),
                          stringAsJsonLiteral: true  // this is json string, include 'as is'
                    )
            );

More options AddRule

var formatter = JsonManager.ComposeFormatter(
                include,
                rules => rules
                    .AddRule<string[]>(GetStringArrayFormatter) // add formatter for special type
                    .AddRule<int[]>((sb, l) => GetStringIntFormatter(sb, l))
                    .AddRule<IEnumerable<Guid>>(GetStringGuidFormatter) 
                    // add formatter for special type but only for subTree
                    .SubTree(
                        chain  => chain.Include(e => e.Test),
                        subRules => subRules.AddRule<int[]>(serializer: GetSumFormatter, propertySerializationName: "Sum"),
                        dateTimeFormat: null, 
                        floatingPointFormat: null
                    ));

Equals

Include<User> include = chain=>chain.Include(e=>e.UserId).IncludeAll(e=>e.Groups).ThenInclude(e=>e.GroupId)

bool b1 = ObjectExtensions.Equals(user1, user2, include);
bool b2 = ObjectExtensions.EqualsAll(userList1, userList2, include);

Clone

Include<User> include = chain=>chain.Include(e=>e.UserId).IncludeAll(e=>e.Groups).ThenInclude(e=>e.GroupId)

var newUser = ObjectExtensions.Clone(user1, include, leafRule1);
var newUserList = ObjectExtensions.CloneAll(userList1, leafRule1);

Copy

Include<User> include = chain=>chain.IncludeAll(e=>e.Groups);

ObjectExtensions.Copy(user1, user2, include, supportedLeafsRule);  
ObjectExtensions.CopyAll(userList1, userList2, include, supportedLeafsRule);

DSL Includes Internal Structures

ChainNode root = include.CreateChainNode();

There root contains .Children - Dictionary<srting, ChainMemberNode>

ChainMemberNode type - additionally contains .Parent - ref to parent.

You can create includes dinamically:

var root = new ChainNode(typeof(Point));
var child = new ChainPropertyNode(
         typeof(int),
         expression: typeof(Point).CreatePropertyLambda("X"),
         memberName:"X", isEnumerable:false, parent:root
);
root.Children.Add("X", child);
// or there is number of extension methods e.g.: var child = root.AddChild("X");

Include<Point> include = ChainNodeExtensions.ComposeInclude<Point>(root);

DSL Includes Meta operations

Add leafs by rule

Func<ChainNode, MemberName> leafRule = ... //
inlcude.AppendLeafs(leafRule ?? LeafRuleManager.DefaultEfCore);

Compare:

var b1 = InlcudeExtensions.IsEqualTo(include1, include2);
var b2 = InlcudeExtensions.IsSubTreeOf(include1, include2);
var b3 = InlcudeExtensions.IsSuperTreeOf(include1, include2);

Clone:

var include2 = InlcudeExtensions.Clone(include1);

Merge:

var include3 = InlcudeExtensions.Equals(include1, include2);

Get XPATH to all leafs:

IReadOnlyCollection<string> paths1 = InlcudeExtensions.ListLeafXPaths(include);

Coverage Status

You can’t perform that action at this time.