I'm having a problem with the comparer as it is generating a new object everytime I make a meaningless change (e.g. add a space) to the file that is being inspected. More specifically, it is generating ALL objects.
I've added some temporary code (and suppressed error about File) to dump the comparison. For every object I see basically the same thing, top line is True and Bottom line is False
ClassInformation: PersonBuilder and PersonBuilder = True True
InterfaceInformation: Person and Person = False False
So I know the where the problem starts. I then added another method to dump the contents of the object as JSON and compared the results and the contents are identical in all manners (values / order / etc)
My object structures are all "public record xxx" to take advantage of the built in equality comparisons so I don't have to write them. The only comparer I wrote is for the generator itself, which is below with the simple objects.
So what am I missing?
using Newtonsoft.Json;
namespace WS.Gen.ObjectMother;
public class GeneratorInformationComparer : IEqualityComparer<GeneratorInformation>
{
public static GeneratorInformationComparer Instance { get; } = new();
public bool Equals(GeneratorInformation x, GeneratorInformation y)
{
Write(x?.ClassInformation, y?.ClassInformation);
Write(x?.InterfaceInformation, y?.InterfaceInformation);
Write($"{x?.InterfaceInformation.ClassName}.x.json", JsonConvert.SerializeObject(x?.InterfaceInformation, Formatting.Indented));
Write($"{y?.InterfaceInformation.ClassName}.y.json", JsonConvert.SerializeObject(y?.InterfaceInformation, Formatting.Indented));
if (x == null || y == null)
return x == y;
return
x.ClassInformation.Equals(y.ClassInformation) &&
x.InterfaceInformation.Equals(y.InterfaceInformation);
}
public int GetHashCode(GeneratorInformation obj)
{
var hashCodes = new List<int>
{
obj.ClassInformation.GetHashCode(),
obj.InterfaceInformation.GetHashCode()
};
return hashCodes.Aggregate(CombineHashCodes);
}
protected static int CombineHashCodes(int left, int right)
{
unchecked
{
// Copied from - .Web/Util/HashCodeCombiner.cs
return ((left << 5) + left) ^ right;
}
}
//
// Debug code
//
public void Write(string filename, string? text)
{
const string path = "D:\\temp\\Output\\";
File.AppendAllText(Path.Combine(path, filename), text);
}
public void Write(ClassInformation? x, ClassInformation? y)
{
const string fn = "D:\\temp\\Output\\TextFile.txt";
File.AppendAllText(fn, $"ClassInformation: {x?.ClassName} and {y?.ClassName} = {x == y} {x!.Equals(y!)}\n");
}
public void Write(InterfaceInformation? x, InterfaceInformation? y)
{
const string fn = "D:\\temp\\Output\\TextFile.txt";
File.AppendAllText(fn, $"InterfaceInformation: {x?.ClassName} and {y?.ClassName} = {x == y} {x!.Equals(y!)}\n");
}
}
public record GeneratorInformation
(
ClassInformation ClassInformation,
InterfaceInformation InterfaceInformation
);
public record ClassInformation
(
string Namespace,
string ClassName,
NullableContextOptions NullableContextOptions = NullableContextOptions.Disable
);
public record InterfaceInformation
(
string Namespace,
string ClassName,
bool GenerateSample,
List<ConstructorInformation> Constructors,
List<ClassMember> Properties,
List<ClassMember> Fields,
InterfaceInformation? Inherited
);
public record ConstructorInformation
(
Accessibility Accessibility,
IDictionary<string, ConstructorParameters> ConstructorParameters
)
{
public bool IsParameterless => !ConstructorParameters.Values.Any();
};
public record ConstructorParameters
(
string DataType,
string ParameterName,
int Order
);
public record ClassMember
(
Accessibility Accessibility,
ClassMemberType ClassMemberType,
string DataType,
string Name,
bool IsReadOnly,
bool IsValueType,
bool IsGenericType,
bool IsCollection,
bool IsNullable
) : IClassMemberInfo
{
private string? _fieldName;
public string FieldName => _fieldName ??= GetFieldName();
private string GetFieldName()
=> $"_{ToLowerChar()}{Name.Substring(1)}";
private string ToLowerChar()
=> Name.ToLower().Substring(0, 1);
}