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.

License

Notifications You must be signed in to change notification settings

xsysfan/Routines

This branch is 1 commit ahead of, 14 commits behind DashboardCode/Routines:master.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

6f16247 · Nov 27, 2020
Aug 1, 2020
Aug 11, 2018
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Jul 25, 2020
Aug 25, 2018
Jul 25, 2020
Jul 25, 2020
Dec 4, 2016
Nov 14, 2017
Aug 30, 2017
Jul 2, 2018
Mar 31, 2018
Mar 24, 2018
Mar 31, 2018
Oct 30, 2017
Dec 4, 2016
Dec 7, 2017
Sep 8, 2020
Dec 7, 2016
Aug 15, 2020
Aug 2, 2018
Nov 27, 2020
Sep 8, 2020
Jul 25, 2020

Repository files navigation

Routines

Fixing abstractions

Functional framework to compose functions parametrized by object navigation expression (such functions as "clone", "compare", "serialize" etc.). Provides additional abstractions for function's composition.

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

About

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.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 68.9%
  • JavaScript 12.9%
  • HTML 8.5%
  • CSS 7.0%
  • PowerShell 1.2%
  • TypeScript 1.1%
  • Other 0.4%