Skip to content

Commit

Permalink
Update for .NET 8
Browse files Browse the repository at this point in the history
  • Loading branch information
dbolin committed Nov 26, 2023
1 parent ba50a56 commit 2484274
Show file tree
Hide file tree
Showing 14 changed files with 81 additions and 78 deletions.
10 changes: 5 additions & 5 deletions Apex.Serialization/Apex.Serialization.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6</TargetFrameworks>
<Version>4.0.5</Version>
<TargetFrameworks>net8</TargetFrameworks>
<Version>5.0.0</Version>
<Authors>Dominic Bolin</Authors>
<Description>A high performance contract-less binary serializer</Description>
<PackageProjectUrl>https://github.com/dbolin/Apex.Serialization</PackageProjectUrl>
Expand Down Expand Up @@ -30,7 +30,7 @@

<ItemGroup>
<PackageReference Include="Apex.Analyzers.Immutable.Attributes" Version="1.0.1" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
Expand All @@ -43,8 +43,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Mono.Cecil" Version="0.11.4" />
<PackageReference Include="System.Collections.Immutable" Version="6.0.0" />
<PackageReference Include="Mono.Cecil" Version="0.11.5" />
<PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
<PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
</ItemGroup>
Expand Down
3 changes: 2 additions & 1 deletion Apex.Serialization/Internal/DynamicCode.Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;

Expand All @@ -14,7 +15,7 @@ internal static partial class DynamicCode<TStream, TBinary>
where TStream : IBinaryStream
where TBinary : ISerializer
{
internal static MethodInfo GetUnitializedObjectMethodInfo = typeof(FormatterServices).GetMethod("GetUninitializedObject")!;
internal static MethodInfo GetUnitializedObjectMethodInfo = typeof(RuntimeHelpers).GetMethod("GetUninitializedObject")!;
private static MethodInfo fieldInfoSetValueMethod = typeof(FieldInfo).GetMethod("SetValue", new[] { typeof(object), typeof(object) })!;

private static Expression ReserveConstantSize(ParameterExpression stream, int size)
Expand Down
31 changes: 22 additions & 9 deletions Apex.Serialization/Internal/DynamicCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,16 @@ private static Expression AfterDeserializeCallExpression(Type type, MethodInfo m
var custom = HandleCustomRead(type, output, stream, result, settings, readMetadata);
if (custom != null)
{
created = false;
created = true;
if (!type.IsValueType && settings.SerializationMode == Mode.Graph)
{
return Expression.Block(
custom,
Expression.Call(Expression.Call(output, SavedReferencesGetter),
SavedReferencesListAdd, result),
result
);
}
return custom;
}

Expand Down Expand Up @@ -976,22 +985,26 @@ private static Expression AfterDeserializeCallExpression(Type type, MethodInfo m
if (customContextType != null)
{
var customContext = Expression.Call(output, CustomContextGetter.MakeGenericMethod(customContextType));
customReadStatements.Add(Expression.Call(
customReadStatements.Add(
Expression.Assign(result,
Expression.Call(
Expression.Convert(
Expression.Constant(entry.Value.Action),
typeof(Action<,,>).MakeGenericType(type, typeof(IBinaryReader), customContextType)),
entry.Value.InvokeMethodInfo, result,
typeof(Func<,,>).MakeGenericType(typeof(IBinaryReader), customContextType, type)),
entry.Value.InvokeMethodInfo,
Expression.Call(output, BinaryReaderGetter),
customContext));
customContext)));
}
else
{
customReadStatements.Add(Expression.Call(
customReadStatements.Add(
Expression.Assign(result,
Expression.Call(
Expression.Convert(
Expression.Constant(entry.Value.Action),
typeof(Action<,>).MakeGenericType(type, typeof(IBinaryReader))),
entry.Value.InvokeMethodInfo, result,
Expression.Call(output, BinaryReaderGetter)));
typeof(Func<,>).MakeGenericType(typeof(IBinaryReader), type)),
entry.Value.InvokeMethodInfo,
Expression.Call(output, BinaryReaderGetter))));
}
}
}
Expand Down
33 changes: 8 additions & 25 deletions Apex.Serialization/Internal/Reflection/FieldInfoModifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,14 @@ static FieldInfoModifier()
var fieldInfo_m_Attributes = type?.GetField("m_fieldAttributes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo_m_Attributes != null)
{
var fieldInfoParam = Expression.Parameter(typeof(FieldInfo));
var castedType = Expression.Convert(fieldInfoParam, type!);
var returnLabel = Expression.Label();
SetFieldInfoNotReadonly = (Action<FieldInfo>)Expression.Lambda(
Expression.Block(
Expression.Assign(Expression.MakeMemberAccess(castedType, fieldInfo_m_Attributes),
Expression.Convert(Expression.And(Expression.Convert(Expression.MakeMemberAccess(castedType, fieldInfo_m_Attributes), typeof(int)), Expression.Constant((int)(~FieldAttributes.InitOnly)))
,typeof(FieldAttributes))
)
, Expression.Return(returnLabel),
Expression.Label(returnLabel)
)
, fieldInfoParam
).Compile();
SetFieldInfoReadonly = (Action<FieldInfo>)Expression.Lambda(
Expression.Block(
Expression.Assign(Expression.MakeMemberAccess(castedType, fieldInfo_m_Attributes),
Expression.Convert(Expression.Or(Expression.Convert(Expression.MakeMemberAccess(castedType, fieldInfo_m_Attributes), typeof(int)), Expression.Constant((int)(FieldAttributes.InitOnly)))
, typeof(FieldAttributes))
)
, Expression.Return(returnLabel),
Expression.Label(returnLabel)
)
, fieldInfoParam
).Compile();
SetFieldInfoNotReadonly = f =>
{
fieldInfo_m_Attributes.SetValue(f, ((FieldAttributes)fieldInfo_m_Attributes.GetValue(f)!) & ~FieldAttributes.InitOnly);
};
SetFieldInfoReadonly = f =>
{
fieldInfo_m_Attributes.SetValue(f, ((FieldAttributes)fieldInfo_m_Attributes.GetValue(f)!) | FieldAttributes.InitOnly);
};

var s = Binary.Create(new Settings { UseSerializedVersionId = false });
try
Expand Down
10 changes: 6 additions & 4 deletions Apex.Serialization/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ public sealed class Settings
/// </summary>
/// <typeparam name="T">Type to which the custom serialization will apply. Does not support primitives.</typeparam>
/// <param name="writeMethod">Method to be called when a type matching T is to be serialized.</param>
public Settings RegisterCustomSerializer<T>(Action<T, IBinaryWriter> writeMethod, Action<T, IBinaryReader> readMethod)
/// <param name="readMethod">Method to be called when a type matching T is to be deserialized.</param>
public Settings RegisterCustomSerializer<T>(Action<T, IBinaryWriter> writeMethod, Func<IBinaryReader, T> readMethod)
{
CustomActionSerializers.Add(typeof(T), new CustomSerializerDelegate(
writeMethod,
Expand All @@ -55,7 +56,7 @@ public Settings RegisterCustomSerializer<T>(Action<T, IBinaryWriter> writeMethod
));
CustomActionDeserializers.Add(typeof(T), new CustomSerializerDelegate(
readMethod,
typeof(Action<T, IBinaryReader>).GetMethod("Invoke")!,
typeof(Func<IBinaryReader, T>).GetMethod("Invoke")!,
null));
return this;
}
Expand All @@ -66,7 +67,8 @@ public Settings RegisterCustomSerializer<T>(Action<T, IBinaryWriter> writeMethod
/// <typeparam name="T">Type to which the custom serialization will apply. Does not support primitives.</typeparam>
/// <typeparam name="TContext">Type of custom serialization context. Will be null if the current context is not set or cannot be cast to this type.</typeparam>
/// <param name="writeMethod">Method to be called when a type matching T is to be serialized.</param>
public Settings RegisterCustomSerializer<T, TContext>(Action<T, IBinaryWriter, TContext> writeMethod, Action<T, IBinaryReader, TContext> readMethod)
/// <param name="readMethod">Method to be called when a type matching T is to be deserialized.</param>
public Settings RegisterCustomSerializer<T, TContext>(Action<T, IBinaryWriter, TContext> writeMethod, Func<IBinaryReader, TContext, T> readMethod)
where TContext : class
{
CustomActionSerializers.Add(typeof(T), new CustomSerializerDelegate(
Expand All @@ -76,7 +78,7 @@ public Settings RegisterCustomSerializer<T, TContext>(Action<T, IBinaryWriter, T
));
CustomActionDeserializers.Add(typeof(T), new CustomSerializerDelegate(
readMethod,
typeof(Action<T, IBinaryReader, TContext>).GetMethod("Invoke")!,
typeof(Func<IBinaryReader, TContext, T>).GetMethod("Invoke")!,
typeof(TContext)
));
return this;
Expand Down
8 changes: 4 additions & 4 deletions Benchmark/Benchmark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6</TargetFramework>
<TargetFramework>net8</TargetFramework>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Benchmark.snk</AssemblyOriginatorKeyFile>
<LangVersion>8.0</LangVersion>
Expand All @@ -12,11 +12,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.1" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.10" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.10" />
<PackageReference Include="Ceras" Version="4.1.7" />
<PackageReference Include="Ceras.ImmutableCollections" Version="1.0.0" />
<PackageReference Include="FluentAssertions" Version="6.10.0" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Hyperion" Version="0.12.0" />
<PackageReference Include="MessagePack" Version="2.3.85" />
<PackageReference Include="MessagePack.ImmutableCollection" Version="2.3.85" />
Expand Down
2 changes: 1 addition & 1 deletion Benchmark/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public Config()
AddExporter(DefaultConfig.Instance.GetExporters().ToArray()); // manual config has no exporters by default
AddColumnProvider(DefaultConfig.Instance.GetColumnProviders().ToArray()); // manual config has no columns by default

AddJob(Job.Default.WithToolchain(CsProjCoreToolchain.NetCoreApp60).WithGcServer(true));
AddJob(Job.Default.WithToolchain(CsProjCoreToolchain.NetCoreApp80).WithGcServer(true));
//AddJob(Job.Clr.With(CsProjClassicNetToolchain.Net472));
//AddJob(Job.CoreRT);
//Add(HardwareCounter.BranchMispredictions, HardwareCounter.BranchInstructions);
Expand Down
2 changes: 1 addition & 1 deletion DeserializeTest/DeserializeTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6</TargetFramework>
<TargetFramework>net8</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion DeserializeTest2/DeserializeTest2.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6</TargetFramework>
<TargetFramework>net8</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
14 changes: 7 additions & 7 deletions Tests/Apex.Serialization.Tests/Apex.Serialization.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6</TargetFrameworks>
<TargetFrameworks>net8</TargetFrameworks>
<IsPackable>false</IsPackable>
<LangVersion>8.0</LangVersion>
<SignAssembly>true</SignAssembly>
Expand All @@ -13,16 +13,16 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="3.2.0">
<PackageReference Include="coverlet.msbuild" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.10.0" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="System.Collections.Immutable" Version="6.0.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
<PackageReference Include="xunit" Version="2.6.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Expand Down
4 changes: 2 additions & 2 deletions Tests/Apex.Serialization.Tests/ConstructedSettingsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public static void Serialize(Test t, IBinaryWriter writer)
writer.Write(t.Value - 1);
}

public static void Deserialize(Test t, IBinaryReader reader)
public static Test Deserialize(IBinaryReader reader)
{
t.Value = reader.Read<int>();
return new Test { Value = reader.Read<int>() };
}
}

Expand Down
9 changes: 5 additions & 4 deletions Tests/Apex.Serialization.Tests/ConstructorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime.Serialization;
using System.Runtime.CompilerServices;
using System.Text;
using FluentAssertions;
using Xunit;
Expand Down Expand Up @@ -239,7 +240,7 @@ public void Throw()
[Fact]
public void ConstructorThatThrows()
{
var x = (ThrowsOnConstruct) FormatterServices.GetUninitializedObject(typeof(ThrowsOnConstruct));
var x = (ThrowsOnConstruct) RuntimeHelpers.GetUninitializedObject(typeof(ThrowsOnConstruct));
x.A = 3;

RoundTrip(x);
Expand All @@ -259,7 +260,7 @@ public ConstructorSettingStaticField(int a)
[Fact]
public void ConstructorThatSetsStaticField()
{
var x = (ConstructorSettingStaticField)FormatterServices.GetUninitializedObject(typeof(ConstructorSettingStaticField));
var x = (ConstructorSettingStaticField) RuntimeHelpers.GetUninitializedObject(typeof(ConstructorSettingStaticField));
x.A = 3;

RoundTrip(x, (x, y) => { ConstructorSettingStaticField.B.Should().Be(0); y.A.Should().Be(3); });
Expand All @@ -286,7 +287,7 @@ private void Set(int a)
[Fact]
public void ConstructorThatSetsStaticFieldIndirect()
{
var x = (ConstructorSettingStaticFieldIndirect)FormatterServices.GetUninitializedObject(typeof(ConstructorSettingStaticFieldIndirect));
var x = (ConstructorSettingStaticFieldIndirect) RuntimeHelpers.GetUninitializedObject(typeof(ConstructorSettingStaticFieldIndirect));
x.A = 3;

RoundTrip(x, (x, y) => { ConstructorSettingStaticFieldIndirect.B.Should().Be(0); y.A.Should().Be(3); });
Expand Down Expand Up @@ -315,7 +316,7 @@ public DerivedClassWithBaseConstructor(int a) : base()
[Fact]
public void TestDerivedClassWithBaseConstructorSideEffects()
{
var x = (DerivedClassWithBaseConstructor)FormatterServices.GetUninitializedObject(typeof(DerivedClassWithBaseConstructor));
var x = (DerivedClassWithBaseConstructor) RuntimeHelpers.GetUninitializedObject(typeof(DerivedClassWithBaseConstructor));
x.A = 3;

RoundTrip(x);
Expand Down
18 changes: 11 additions & 7 deletions Tests/Apex.Serialization.Tests/CustomSerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,17 @@ public static void Serialize(Test t, IBinaryWriter writer)
}
}

public static void Deserialize(Test t, IBinaryReader reader)
public static Test Deserialize(IBinaryReader reader)
{
var t = new Test();
t.Value = reader.Read<int>();
var isNotNullByte = reader.Read<byte>();
if (isNotNullByte == 1)
{
t.Nested = reader.ReadObject<Test>();
}

return t;
}
}

Expand All @@ -53,9 +56,9 @@ public static void Serialize(TestCustomContext t, IBinaryWriter writer, CustomCo
writer.Write(context.ValueOverride);
}

public static void Deserialize(TestCustomContext t, IBinaryReader reader, CustomContext context)
public static TestCustomContext Deserialize(IBinaryReader reader, CustomContext context)
{
t.Value = context.ValueOverride;
return new TestCustomContext { Value = context.ValueOverride };
}
}

Expand All @@ -76,14 +79,16 @@ public CustomSerializationTests()
{
s.WriteObject(i);
}
}, (o, s) =>
}, (s) =>
{
var o = new HashSet<Test>();
var count = s.Read<int>();
o.EnsureCapacity(count);
for (int i = 0; i < count; ++i)
{
o.Add(s.ReadObject<Test>());
}
return o;
});
};
}
Expand Down Expand Up @@ -170,10 +175,9 @@ public static void Serialize(TestWithConstructor t, IBinaryWriter writer)
writer.Write(t.Value - 1);
}

public static void Deserialize(TestWithConstructor t, IBinaryReader reader)
public static TestWithConstructor Deserialize(IBinaryReader reader)
{
t.Value.Should().Be(0);
t.Value = reader.Read<int>();
return new TestWithConstructor(reader.Read<int>());
}
}

Expand Down
Loading

0 comments on commit 2484274

Please sign in to comment.