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

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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%