最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

sourcegenerators - Roslyn IIncrementalGenerator - Comparer not working - know where - not why - Stack Overflow

programmeradmin2浏览0评论

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);
}




发布评论

评论列表(0)

  1. 暂无评论