Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failing DeepCopy when implementing multiple IConverter<,> on single class #8879

Open
ccorsano opened this issue Feb 25, 2024 · 0 comments
Open

Comments

@ccorsano
Copy link

ccorsano commented Feb 25, 2024

I am experimenting conversion from Orleans 3.x to 8.x using a personal project, and ran into a runtime crash when declaring surrogate types and converters.

When implementing multiple IConverter<,> interfaces in a single converter class, compilation and initialization is fine, but serialization fails with a System.InvalidCastException, due a mis-selection of the ICopier to use.

A simple fix would be to check for the IConverter<,> first type argument when selecting the copier.

Another option would be to discourage using a single converter for multiple surrogate type, in which case an error diagnostic would be helpful.

Repro code:

    public class MyFirstForeignLibraryType
    {
        
        public int Num { get; set; }
        public string String { get; set; }
        public DateTimeOffset DateTimeOffset { get; set; }

        public override bool Equals(object obj) =>
            obj is MyFirstForeignLibraryType type
            && Num == type.Num
            && string.Equals(String, type.String, StringComparison.Ordinal)
            && DateTimeOffset.Equals(type.DateTimeOffset);

        public override int GetHashCode() => HashCode.Combine(Num, String, DateTimeOffset);
    }

    public class MySecondForeignLibraryType
    {
        public string Name { get; set; }
        public float Value { get; set; }
        public DateTimeOffset Timestamp { get; set; }

        public override bool Equals(object obj) =>
            obj is MySecondForeignLibraryType type
            && string.Equals(Name, type.Name, StringComparison.Ordinal)
            && Value == type.Value
            && Timestamp.Equals(type.Timestamp);

        public override int GetHashCode() => HashCode.Combine(Name, Value, Timestamp);
    }

    [GenerateSerializer]
    public struct MyFirstForeignLibraryTypeSurrogate
    {
        [Id(0)]
        public int Num { get; set; }

        [Id(1)]
        public string String { get; set; }

        [Id(2)]
        public DateTimeOffset DateTimeOffset { get; set; }
    }


    [GenerateSerializer]
    public struct MySecondForeignLibraryTypeSurrogate
    {
        [Id(0)]
        public string Name { get; set; }

        [Id(1)]
        public float Value { get; set; }

        [Id(2)]
        public DateTimeOffset Timestamp { get; set; }
    }

    [RegisterConverter]
    public sealed class MyCombinedForeignLibraryValueTypeSurrogateConverter :
        IConverter<MyFirstForeignLibraryType, MyFirstForeignLibraryTypeSurrogate>,
        IConverter<MySecondForeignLibraryType, MySecondForeignLibraryTypeSurrogate>
    {
        public MyFirstForeignLibraryType ConvertFromSurrogate(in MyFirstForeignLibraryTypeSurrogate surrogate)
            => new () { Num = surrogate.Num, String = surrogate.String, DateTimeOffset = surrogate.DateTimeOffset };
        public MyFirstForeignLibraryTypeSurrogate ConvertToSurrogate(in MyFirstForeignLibraryType value)
            => new() { Num = value.Num, String = value.String, DateTimeOffset = value.DateTimeOffset };

        public MySecondForeignLibraryType ConvertFromSurrogate(in MySecondForeignLibraryTypeSurrogate surrogate)
            => new() { Name = surrogate.Name, Value = surrogate.Value, Timestamp = surrogate.Timestamp };
        public MySecondForeignLibraryTypeSurrogate ConvertToSurrogate(in MySecondForeignLibraryType value)
            => new () { Name = value.Name, Value = value.Value, Timestamp = value.Timestamp };
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant