khalidsalomao / simplehelpers.net Goto Github PK
View Code? Open in Web Editor NEWMicro-libraries (pieces of utility code) for .Net that are safe and simple to use
Home Page: http://khalidsalomao.github.io/SimpleHelpers.Net/
License: MIT License
Micro-libraries (pieces of utility code) for .Net that are safe and simple to use
Home Page: http://khalidsalomao.github.io/SimpleHelpers.Net/
License: MIT License
Hi Khalid,
First of all, thanks for the very useful library, I'm using it in a client project. I haven't found another implementation that is as handy and low-ceremony as yours ๐
I just found a little issue in sub-collections, let me explain it.
If you have an original object:
{ "Children": [ { "Name": "Alice" } ] }
and a modified one:
{ "Children": [ { "Name": "Alice" }, { "Name": "Bob" } ] }
If I do a GenerateDiff and then PatchObject one the original object, I get this:
{ "Children": [ {"Name": "Alice"}, null ] }
I have addressed the issue by making 2 small changes in the Patch method:
'return array' in the block that deals with arrays, 'return sourceObj' in the block that deals with objects, and remove the 'return sourceJson' at the end of the method. Problem is then fixed, and I think the code is a bit less confusing as well.
Attached is a small unit test that highlights the issue.
Would be awesome if you could integrate this fix, thx :)
Hi,
Can you explain how to r emoves all items that meets the search parameters with FindAndRemove()
method?
for example
// Get first inserted row
var row = _sqliteStorageDB.Get().FirstOrDefault();
// Find & Remove this row
_sqliteStorageDB.FindAndRemove( "row. How to do it?");
Thanks
I think you need add clause
else if (rawData[start + 1] == 0xfe && rawData[start] == 0xff)
{
// Encoding.Unicode (Little-Endian)
return true;
}
to CheckForByteOrderMark function.
I'm not sure if it's correct to report this as an issue, but I ran into a problem with the CheckForTextualData function, in particular this check:
else if (rawData[i - 1] == 0 && rawData[i] < 10) { ++controlSequences; }
The char
represented by the number 9 is Tab. I'm working with an ERP system that requires export files to be Tab-separated, so when I passed in an exported string with lots of tabs, it failed to pass this test. The solution was to check rawData[i] < 9
instead of rawData[i] < 10
I don't understand why, but when I change items in a list that had items the comparison is retuning an object instead of an array.
I'm going to list 3 cases, the first 2 go by as expected:
var company = new Company(15)
{
Name = "Sega"
};
var previousCat = new Category(1)
{
Name = "Cat X",
Department = new Department(100)
{
Name = "Department 100",
Company = company
},
Companies = new List<Company>()
};
var currentCat = new Category(1)
{
Name = "Cat XYZ",
Department = new Department(100)
{
Name = "Department 100",
Company = company
},
Companies = new List<Company> { company }
};
Result as expected*
// New Value:
[
{
"Name": "Sega",
"Categories": null,
"Id": 15
}
]
// Old value:
[]
var company = new Company(15)
{
Name = "Sega"
};
var previousCat = new Category(1)
{
Name = "Cat X",
Department = new Department(100)
{
Name = "Department 100",
Company = company
},
Companies = new List<Company>
{
company
}
};
var currentCat = new Category(1)
{
Name = "Cat XYZ",
Department = new Department(100)
{
Name = "Department 100",
Company = company
},
Companies = new List<Company>()
};
Result as expected*
// New value:
[]
// Old Value:
[
{
"Name": "Sega",
"Categories": null,
"Id": 15
}
]
var sega = new Company(15)
{
Name = "Sega"
};
var sony = new Company(30)
{
Name = "Sony"
};
var nintendo = new Company(45)
{
Name = "Nintendo"
};
var microsoft = new Company(60)
{
Name = "Microsoft"
};
var previousCat = new Category(1)
{
Name = "Cat X",
Department = new Department(100)
{
Name = "Department 100",
Company = sega
},
Companies = new List<Company>
{
sega,
nintendo
}
};
var currentCat = new Category(1)
{
Name = "Cat XYZ",
Department = new Department(100)
{
Name = "Department 100",
Company = sega
},
Companies = new List<Company>
{
nintendo,
sony,
microsoft
}
};
Result NOT as expected*
// New value:
{
"0": {
"Name": "Nintendo",
"Id": 45
},
"1": {
"Name": "Sony",
"Id": 30
},
"2": {
"Name": "Microsoft",
"Categories": null,
"Id": 60
},
"@@ Count": 3
}
// Old value:
{
"0": {
"Name": "Sega",
"Id": 15
},
"1": {
"Name": "Nintendo",
"Id": 45
},
"@@ Count": 2
}
As you can see the third result returns an object, not an array. Why is that?
Hi
Circular references are not supported by your library. I think it would be possible to support this by using PreserveReferencesHandling = PreserveReferencesHandling.All
in the Newtonsoft serializer settings.
But of course a whole new level of complexity would be added.
Here a simple unit test (nunit-framework) with an example:
private class CircularObject
{
private CircularObject child;
public CircularObject Child
{
get { return child; }
set { child = value; }
}
private CircularObject parent;
public CircularObject Parent
{
get { return parent; }
set { parent = value; }
}
}
[Test]
public void CircularReferencesTest()
{
CircularObject clientModel = new CircularObject();
CircularObject serverModel = new CircularObject(); //equal object (with respect to properties)
//start using ObjectDiffPatch
var snapshot = ObjectDiffPatch.Snapshot(clientModel);
//make a change (this is a cyclic reference)
clientModel.Child = new CircularObject();
clientModel.Child.Parent = clientModel;
//create diff
var diff = ObjectDiffPatch.GenerateDiff(snapshot, clientModel);
//apply diff on server side
serverModel = ObjectDiffPatch.PatchObject(serverModel, diff.NewValues);
//ensure everything is alright
Assert.AreEqual(serverModel, serverModel.Child.Parent);
}
Hi, i like the DiffPatch Generator, makes a lot of work for me. As for a Simple Helper i use many times:
using System;
using System.Linq;
using System.Reflection;
using System.Text;
#pragma warning disable CS1591
namespace Helper {
public sealed class Object2String<T> : IObject2String<T> {
public string ToString(T obj) {
StringBuilder toReturn = new StringBuilder($"{obj.GetType().Name} -> ");
var publicPropertys = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
var primitivePropertys = publicPropertys.Where(prop => prop.PropertyType.IsPrimitive || prop.PropertyType.IsValueType || prop.PropertyType == typeof(string)).ToList();
var nonPrimitivePropertys = publicPropertys.Where(prop => !(prop.PropertyType.IsPrimitive || prop.PropertyType.IsValueType || prop.PropertyType == typeof(string))).ToList();
primitivePropertys.ForEach(prop => toReturn.Append($"{prop.Name}: {prop.GetValue(obj)?.ToString()} "));
nonPrimitivePropertys.ForEach(
prop => {
if (prop.GetValue(obj) != null)
toReturn.Append($"| {prop.GetValue(obj)?.ToString()} ");
}
);
return toReturn.ToString().Substring(0, toReturn.ToString().Length - 1);
}
}
}
#pragma warning restore CS1591
Should i put an Pull Request or is it "too simple" for you :)
This line fails with NullReferenceException
if, target
was null
on the original object. Newtonsoft parses this value to a JToken
with type Null.
SimpleHelpers.Net/SimpleHelpers/ObjectDiffPatch.cs
Lines 268 to 273 in 6043344
Hi,
What is the most optimized method to Remove and Returns the first element of the table stored at key like LPOP Redis Command.
I do this, but I have long processing time when there are lots of records
// create a new instance
SQLiteStorage<My_Class> db = new SQLiteStorage<My_Class> ("path_to_my_file.sqlite", SQLiteStorageOptions.UniqueKeys ());
db.Set ("key1", new My_Class ());
db.Set ("key2", new My_Class ());
db.Set ("key3", new My_Class ());
// ... save more items with associated keys
// Get the first element of the table.
// => long processing time when there are lots of records
var My_Class_Details = db.GetDetails().First();
// Remove this first element
db.Remove(My_Class_Details.Key);
Lock removal at line 75, currently looks like this:
if (padlock.Decrement () <= 0)
m_waitLock.TryRemove (key, out padlock);
Since this operation is not atomic, it is possible for a different thread to acquire the padlock
before the if
statement, but increment it after the if
statement. So, thread T1
will remove the padlock
while thread T2
starts the critical section, meaning that if a third thread enters GetOrAdd
while T2
is working, it will get a new padlock
instance.
To avoid a global lock, perhaps having a while
loop inside GetOrAdd
would ensure that the incremented lock wasn't removed from the dictionary:
private static object GetOrAdd (string key)
{
CountedLock padlock = null;
while (true)
{
padlock = m_waitLock.GetOrAdd (key, LockFactory);
padlock.Increment ();
// double check that things haven't changed
if (padlock == m_waitLock.GetOrAdd (key, LockFactory))
return padlock;
// oops
padlock.Decrement ();
};
}
This is off top of my head, I still have to check a bit more if it makes sense.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.