How to compare Acumatica objects without ObjectsEqual

Hello everybody,

Long time ago I made a post on how to extend if needed method  ObjectsEqual in Acumatica.

today I want to extend my answer a bit more and share with you class OneLevelComparer. With help of this class you may check if some object was changed without need of typing all fields of DAC class. Take a look on the class itself:

/// <summary>
/// Comparison of two objects on equality based on reflection. 
/// Doesn't support inner collections, objects.
/// </summary>
public static class OneLevelComparer
{
	// Item1: property name, Item2 current, Item3 original
	public static List<Tuple<stringobjectobject>> Differences<T>(T current, T original)
	{
		var diffs = new List<Tuple<stringobjectobject>>();
 
		MethodInfo areEqualMethod = typeof(OneLevelComparer).GetMethod("AreEqual"BindingFlags.Static | BindingFlags.NonPublic);
 
		foreach (PropertyInfo prop in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
		{
			object x = prop.GetValue(current);
			object y = prop.GetValue(original);
			bool areEqual = (bool)areEqualMethod.MakeGenericMethod(prop.PropertyType).Invoke(nullnew object[] { x, y });
 
			if (!areEqual)
			{
				diffs.Add(Tuple.Create(prop.Name, x, y));
			}
		}
 
		return diffs;
	}
 
	private static bool AreEqual<T>(T x, T y)
	{
		return EqualityComparer<T>.Default.Equals(x, y);
	}
}

Then further in the code you may build your conclusions depending of changes for example like this:

var changes = OneLevelComparer.Differences(currentApSetup, apSetupOriginal);
foreach (Tuple<stringobjectobject> change in changes)
{
	if(change.Item1 == "tstamp")
		continue;
	if(change.Item1 == "LastModifiedDateTime")
		continue;

etc...

Acumatica and ObjectsEqual lack of parameters

Hello everybody,

today I want to share how I deal with ObjectsEqual limitation. In one of my tasks I had requirement to check for equality more then eight parameters and found that ObjectsEqual takes only 8 parameters. But I needed more. 

In order to fix it I decided to use extension classes of C# which allows inject into existing class new functionality.

Here is the way how I did it:

public static class PXCacheExtensions
    {
        public static bool ObjectsEqualExt(this PXCache cache, object a, object b, params IBqlField[] values)
        {
            var result = true;
            foreach (var bqlField in values)
            {
                result = result && object.Equals(cache.GetValue<IBqlField>(a), cache.GetValue<IBqlField>(b));
            }

            return result;
        }

        public static bool ObjectsEqual<Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9>(this PXCache cache, object a, object b)
            where Field1 : IBqlField
            where Field2 : IBqlField
            where Field3 : IBqlField
            where Field4 : IBqlField
            where Field5 : IBqlField
            where Field6 : IBqlField
            where Field7 : IBqlField
            where Field8 : IBqlField
            where Field9 : IBqlField
        {
            return (cache.ObjectsEqual<Field9>(a, b) && cache.ObjectsEqual<Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8>(a, b));
        }

        public static bool ObjectsEqual<Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10>(this PXCache cache, object a, object b)
            where Field1 : IBqlField
            where Field2 : IBqlField
            where Field3 : IBqlField
            where Field4 : IBqlField
            where Field5 : IBqlField
            where Field6 : IBqlField
            where Field7 : IBqlField
            where Field8 : IBqlField
            where Field9 : IBqlField
            where Field10 : IBqlField
        {
            return (cache.ObjectsEqual<Field10>(a, b) && cache.ObjectsEqual<Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9>(a, b));
        }

        public static bool ObjectsEqual<Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10, Field11>(this PXCache cache, object a, object b)
            where Field1 : IBqlField
            where Field2 : IBqlField
            where Field3 : IBqlField
            where Field4 : IBqlField
            where Field5 : IBqlField
            where Field6 : IBqlField
            where Field7 : IBqlField
            where Field8 : IBqlField
            where Field9 : IBqlField
            where Field10 : IBqlField
            where Field11 : IBqlField
        {
            return (cache.ObjectsEqual<Field11>(a, b) && cache.ObjectsEqual<Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10>(a, b));
        }

        public static bool ObjectsEqual<Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10, Field11, Field12>(this PXCache cache, object a, object b)
            where Field1 : IBqlField
            where Field2 : IBqlField
            where Field3 : IBqlField
            where Field4 : IBqlField
            where Field5 : IBqlField
            where Field6 : IBqlField
            where Field7 : IBqlField
            where Field8 : IBqlField
            where Field9 : IBqlField
            where Field10 : IBqlField
            where Field11 : IBqlField
            where Field12 : IBqlField
        {
            return (cache.ObjectsEqual<Field12>(a, b) && cache.ObjectsEqual<Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10, Field11>(a, b));
        }


    }

After those modifications my cache accepts twelve parameters for comparing