Skip to content

Commit

Permalink
Support implementing multiple IConverter<,> in single converter class (
Browse files Browse the repository at this point in the history
…#8881)

---------

Co-authored-by: Reuben Bond <[email protected]>
  • Loading branch information
ccorsano and ReubenBond authored Jul 8, 2024
1 parent 4cfa850 commit 817eb5e
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 2 deletions.
3 changes: 2 additions & 1 deletion src/Orleans.Serialization/Serializers/CodecProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,8 @@ private bool TryGetSurrogateCodec(Type fieldType, Type searchType, out Type surr
var converterInterfaceArgs = Array.Empty<Type>();
foreach (var @interface in converterType.GetInterfaces())
{
if (@interface.IsConstructedGenericType && @interface.GetGenericTypeDefinition() == typeof(IConverter<,>))
if (@interface.IsConstructedGenericType && @interface.GetGenericTypeDefinition() == typeof(IConverter<,>)
&& @interface.GenericTypeArguments[0] == fieldType)
{
converterInterfaceArgs = @interface.GetGenericArguments();
}
Expand Down
3 changes: 2 additions & 1 deletion src/Orleans.Serialization/Serializers/SurrogateCodec.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#nullable enable
using System;
using System.Buffers;
using System.Diagnostics.CodeAnalysis;
Expand All @@ -24,7 +25,7 @@ public sealed class SurrogateCodec<TField, TSurrogate, TConverter>
private readonly Type _fieldType = typeof(TField);
private readonly IValueSerializer<TSurrogate> _surrogateSerializer;
private readonly IDeepCopier<TSurrogate> _surrogateCopier;
private readonly IPopulator<TField, TSurrogate> _populator;
private readonly IPopulator<TField, TSurrogate>? _populator;
private readonly TConverter _converter;

/// <summary>
Expand Down
12 changes: 12 additions & 0 deletions test/Orleans.Serialization.UnitTests/ConverterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,15 @@ public DerivedConverterCopierTests(ITestOutputHelper output) : base(output)
protected override bool Equals(DerivedFromMyForeignLibraryType left, DerivedFromMyForeignLibraryType right) => ReferenceEquals(left, right) || left.Equals(right);
protected override DerivedFromMyForeignLibraryType[] TestValues => new DerivedFromMyForeignLibraryType[] { null, CreateValue() };
}


public class CombinedConverterCopierTests : CopierTester<MyFirstForeignLibraryType, IDeepCopier<MyFirstForeignLibraryType>>
{
public CombinedConverterCopierTests(ITestOutputHelper output) : base(output)
{
}

protected override MyFirstForeignLibraryType CreateValue() => new() { Num = 12, String = "hi", DateTimeOffset = DateTimeOffset.Now };
protected override bool Equals(MyFirstForeignLibraryType left, MyFirstForeignLibraryType right) => left.Equals(right);
protected override MyFirstForeignLibraryType[] TestValues => new MyFirstForeignLibraryType[] { CreateValue() };
}
74 changes: 74 additions & 0 deletions test/Orleans.Serialization.UnitTests/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -843,4 +843,78 @@ public sealed class ClassWithTypeFields
[Id(2)] public object UntypedValue;
[Id(3)] public Type Type2;
}

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

0 comments on commit 817eb5e

Please sign in to comment.