diff --git a/.gitignore b/.gitignore
index 19ee5f3..4867c4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,3 @@ obj/
riderModule.iml
/_ReSharper.Caches/
.idea
-work
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 822bf2e..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "lib/Il2CppAssemblyUnhollower"]
- path = lib/Il2CppAssemblyUnhollower
- url = https://github.com/NuclearPowered/Il2CppAssemblyUnhollower
diff --git a/AmongUs.props b/AmongUs.props
index 1936a08..8d64e39 100644
--- a/AmongUs.props
+++ b/AmongUs.props
@@ -1,78 +1,14 @@
+
+ Steam
+ NuclearPowered/Mappings:0.1.0-alpha.1
+
+
-
-
- $(AmongUs)\BepInEx\unhollowed\Assembly-CSharp.dll
- False
-
-
- $(AmongUs)\BepInEx\unhollowed\Hazel.dll
- False
-
-
-
-
- $(AmongUs)\BepInEx\core\0Harmony.dll
- False
-
-
- $(AmongUs)\BepInEx\core\BepInEx.Core.dll
- False
-
-
- $(AmongUs)\BepInEx\core\BepInEx.IL2CPP.dll
- False
-
-
- $(AmongUs)\BepInEx\core\SemVer.dll
- False
-
-
-
-
- $(AmongUs)\BepInEx\core\UnhollowerBaseLib.dll
- False
-
-
- $(AmongUs)\BepInEx\unhollowed\Il2Cppmscorlib.dll
- False
-
-
- $(AmongUs)\BepInEx\unhollowed\Il2CppSystem.Core.dll
- False
-
-
-
-
- $(AmongUs)\BepInEx\unhollowed\UnityEngine.dll
- False
-
-
- $(AmongUs)\BepInEx\unhollowed\UnityEngine.CoreModule.dll
- False
-
-
- $(AmongUs)\BepInEx\unhollowed\UnityEngine.InputLegacyModule.dll
- False
-
-
- $(AmongUs)\BepInEx\unhollowed\UnityEngine.IMGUIModule.dll
- False
-
-
- $(AmongUs)\BepInEx\unhollowed\UnityEngine.UI.dll
- False
-
-
- $(AmongUs)\BepInEx\unhollowed\UnityEngine.UIModule.dll
- False
-
+
-
-
-
-
-
+
+
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 0a04128..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,165 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
diff --git a/README.md b/README.md
index c7bbc74..6f84f17 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,3 @@ Featuring amazing features like:
- modded handshake
- *partially* unstripped IMGUI and UI
- a lot of utility methods
-
-## Reactor.OxygenFilter
-
-Library for mapping output of Il2cppDumper, used in
-[NuclearPowered/Il2CppAssemblyUnhollower](https://github.com/NuclearPowered/Il2CppAssemblyUnhollower)
-
-## Reactor.Greenhouse
-
-Standalone program which generates mappings for OxygenFilter
diff --git a/Reactor.Greenhouse/Compiler.cs b/Reactor.Greenhouse/Compiler.cs
deleted file mode 100644
index 4d22319..0000000
--- a/Reactor.Greenhouse/Compiler.cs
+++ /dev/null
@@ -1,199 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text.RegularExpressions;
-using Mono.Cecil;
-using Reactor.OxygenFilter;
-
-namespace Reactor.Greenhouse
-{
- public static class Compiler
- {
- public static void Apply(this Mappings current, Mappings mappings)
- {
- static void ApplyType(List types, MappedType newType)
- {
- var type = types.SingleOrDefault(x => newType.Equals(x));
- if (type == null)
- {
- types.Add(newType);
- }
- else
- {
- type.Mapped = newType.Mapped;
-
- void ApplyMembers(List members, List newMembers)
- {
- foreach (var newMember in newMembers)
- {
- var member = members.SingleOrDefault(x => newMember.Equals(x, false));
-
- if (member == null)
- {
- members.Add(newMember);
- }
- else
- {
- member.Mapped = newMember.Mapped;
- member.Original = newMember.Original;
- }
- }
- }
-
- ApplyMembers(type.Fields, newType.Fields);
- ApplyMembers(type.Properties, newType.Properties);
-
- foreach (var newMember in newType.Methods)
- {
- var member = type.Methods.SingleOrDefault(x => newMember.Equals(x, false));
-
- if (member == null)
- {
- type.Methods.Add(newMember);
- }
- else
- {
- member.Mapped = newMember.Mapped;
- member.Original = newMember.Original;
- member.Parameters = newMember.Parameters;
- }
- }
-
- foreach (var nestedType in newType.Nested)
- {
- ApplyType(type.Nested, nestedType);
- }
- }
- }
-
- foreach (var newType in mappings.Types)
- {
- ApplyType(current.Types, newType);
- }
- }
-
- private static Regex Regex { get; } = new Regex(@"{{(?[\w\.]+)}}", RegexOptions.Compiled);
-
- public static string MapSignature(this OriginalDescriptor original, Mappings mappings)
- {
- var signature = original.Signature;
-
- var matches = Regex.Matches(signature);
- foreach (Match match in matches)
- {
- var group = match.Groups["expression"];
- if (group.Success)
- {
- signature = signature.Replace(match.Value, mappings.FindByMapped(group.Value).Original.Name);
- }
- }
-
- return signature;
- }
-
- private static bool TestField(MappedMember field, TypeDefinition typeDef, FieldDefinition fieldDef, Mappings mappings)
- {
- return (field.Original.Name == null || field.Original.Name == fieldDef.Name) &&
- (field.Original.Index == null || field.Original.Index == typeDef.Fields.IndexOf(fieldDef)) &&
- (field.Original.Signature == null || field.Original.MapSignature(mappings) == fieldDef.GetSignature()) &&
- (field.Original.Const == null || !typeDef.IsEnum && field.Original.Const.Value.Equals(fieldDef.Constant));
- }
-
- private static bool TestMethod(MappedMember method, TypeDefinition typeDef, MethodDefinition methodDef, Mappings mappings)
- {
- return (method.Original.Index == null || method.Original.Index == typeDef.Methods.IndexOf(methodDef)) &&
- (method.Original.Signature == null || method.Original.MapSignature(mappings) == methodDef.GetSignature()) &&
- (method.Original.Name == null || method.Original.Name == methodDef.Name);
- }
-
- private static bool TestProperty(MappedMember property, TypeDefinition typeDef, PropertyDefinition propertyDef, Mappings mappings)
- {
- return (property.Original.Name == null || property.Original.Name == propertyDef.Name) &&
- (property.Original.Index == null || property.Original.Index == typeDef.Properties.IndexOf(propertyDef)) &&
- (property.Original.Signature == null || property.Original.MapSignature(mappings) == propertyDef.GetSignature());
- }
-
- private static bool TestType(MappedType type, TypeDefinition typeDef, Mappings mappings)
- {
- return (type.Original.Name == null || type.Original.Name == typeDef.Name) &&
- type.Methods.All(method => typeDef.Methods.Any(m => TestMethod(method, typeDef, m, mappings))) &&
- type.Fields.All(field => typeDef.Fields.Any(f => TestField(field, typeDef, f, mappings))) &&
- type.Properties.All(property => typeDef.Properties.Any(p => TestProperty(property, typeDef, p, mappings)));
- }
-
- private static void Compile(this MappedType type, TypeDefinition typeDef, Mappings mappings)
- {
- type.Original = new OriginalDescriptor { Name = typeDef.Name };
-
- foreach (var nested in type.Nested)
- {
- var nestedDef = typeDef.NestedTypes.Single(t =>
- TestType(type, t, mappings) &&
- nested.Original.Index == null || typeDef.NestedTypes.IndexOf(t) == nested.Original.Index
- );
-
- nested.Compile(nestedDef, mappings);
- }
-
- foreach (var property in type.Properties)
- {
- try
- {
- var propertyDef = typeDef.Properties.Single(p => TestProperty(property, typeDef, p, mappings));
-
- property.Original = new OriginalDescriptor { Name = propertyDef.Name };
- }
- catch (Exception e)
- {
- throw new Exception($"Compilation of {property} failed", e);
- }
- }
-
- foreach (var field in type.Fields)
- {
- try
- {
- var fieldDef = typeDef.Fields.Single(f => TestField(field, typeDef, f, mappings));
-
- field.Original = new OriginalDescriptor { Name = fieldDef.Name };
- }
- catch (Exception e)
- {
- throw new Exception($"Compilation of {field} failed", e);
- }
- }
-
- foreach (var method in type.Methods)
- {
- try
- {
- var methodDef = typeDef.Methods.Single(m => TestMethod(method, typeDef, m, mappings));
-
- method.Original = new OriginalDescriptor { Name = methodDef.Name, Signature = methodDef.GetSignature() };
- }
- catch (Exception e)
- {
- throw new Exception($"Compilation of {method} failed", e);
- }
- }
- }
-
- public static void Compile(this Mappings mappings, ModuleDefinition moduleDef)
- {
- foreach (var type in mappings.Types)
- {
- try
- {
- var typeDef = moduleDef.Types.Single(t => TestType(type, t, mappings));
-
- type.Compile(typeDef, mappings);
- }
- catch (Exception e)
- {
- throw new Exception($"Compilation of {type} failed", e);
- }
- }
- }
- }
-}
diff --git a/Reactor.Greenhouse/Extensions.cs b/Reactor.Greenhouse/Extensions.cs
deleted file mode 100644
index 0b75195..0000000
--- a/Reactor.Greenhouse/Extensions.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Linq;
-using Mono.Cecil;
-
-namespace Reactor.Greenhouse
-{
- public static class Extensions
- {
- public static CustomAttribute GetCustomAttribute(this ICustomAttributeProvider cap, string attribute)
- {
- if (!cap.HasCustomAttributes)
- {
- return null;
- }
-
- return cap.CustomAttributes.FirstOrDefault(attrib => attrib.AttributeType.FullName == attribute);
- }
-
- public static uint? GetOffset(this MethodDefinition methodDef)
- {
- var attribute = methodDef.GetCustomAttribute("Il2CppDummyDll.AddressAttribute");
- if (attribute == null)
- return null;
-
- var offset = attribute.Fields.Single(x => x.Name == "Offset");
- return new System.ComponentModel.UInt32Converter().ConvertFrom(offset) as uint?;
- }
- }
-}
diff --git a/Reactor.Greenhouse/Generator.cs b/Reactor.Greenhouse/Generator.cs
deleted file mode 100644
index e3ffde1..0000000
--- a/Reactor.Greenhouse/Generator.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using System.Linq;
-using Mono.Cecil;
-using Reactor.OxygenFilter;
-
-namespace Reactor.Greenhouse
-{
- public static class Generator
- {
- public static Mappings Generate(ModuleDefinition old, ModuleDefinition latest)
- {
- var result = new Mappings();
-
- foreach (var oldType in old.Types)
- {
- if (oldType.Name.StartsWith("<") || oldType.Namespace.StartsWith("GoogleMobileAds"))
- continue;
-
- void AddType(TypeDefinition type)
- {
- var mapped = new MappedType(new OriginalDescriptor { Name = type.Name }, oldType.Name);
-
- var i = 0;
- foreach (var field in type.Fields)
- {
- var j = 0;
- var i1 = i;
- var oldFields = oldType.Fields.Where(x => j++ == i1 && x.GetSignature().ToString() == field.GetSignature().ToString()).ToArray();
- if (oldFields.Length == 1)
- {
- var oldField = oldFields.First();
- if (oldField.Name == field.Name || !field.Name.IsObfuscated())
- continue;
-
- mapped.Fields.Add(new MappedMember(new OriginalDescriptor { Index = i1 }, oldField.Name));
- }
-
- i++;
- }
-
- foreach (var method in type.Methods)
- {
- if (!method.HasParameters || method.IsSetter || method.IsGetter)
- {
- continue;
- }
-
- var oldMethods = oldType.Methods.Where(x => x.Name == method.Name && x.Parameters.Count == method.Parameters.Count).ToArray();
- if (oldMethods.Length != 1)
- {
- continue;
- }
-
- var oldMethod = oldMethods.Single();
-
- var oldParameters = oldMethod.Parameters.Select(x => x.Name).ToList();
-
- if (method.Parameters.Select(x => x.Name).SequenceEqual(oldParameters))
- {
- continue;
- }
-
- mapped.Methods.Add(new MappedMethod(new OriginalDescriptor { Name = method.Name, Signature = method.GetSignature() }, null)
- {
- Parameters = oldParameters
- });
- }
-
- if (type.Name == oldType.Name || (!type.Name.IsObfuscated() && !mapped.Fields.Any() && !mapped.Methods.Any()))
- {
- return;
- }
-
- result.Types.Add(mapped);
- }
-
- var exact = latest.Types.FirstOrDefault(x => x.FullName == oldType.FullName);
- if (exact != null)
- {
- AddType(exact);
- continue;
- }
-
- if (oldType.IsEnum)
- {
- var first = oldType.Fields.Select(x => x.Name).ToArray();
- var type = latest.Types.SingleOrDefault(x => x.IsEnum && x.Fields.Select(f => f.Name).SequenceEqual(first));
- if (type != null)
- {
- AddType(type);
- }
-
- continue;
- }
-
- static bool Test(TypeReference typeReference)
- {
- return typeReference.IsGenericParameter || typeReference.Namespace != string.Empty || !typeReference.Name.IsObfuscated();
- }
-
- var methods = oldType.Methods.Where(x => Test(x.ReturnType) && x.Parameters.All(p => Test(p.ParameterType))).Select(x => x.GetSignature()).ToArray();
- var fields = oldType.Fields.Where(x => Test(x.FieldType) && (!x.FieldType.HasGenericParameters || x.FieldType.GenericParameters.All(Test))).Select(x => x.GetSignature()).ToArray();
- var properties = oldType.Properties.Select(x => x.Name).ToArray();
-
- var types = latest.Types
- .Where(t => t.Attributes == oldType.Attributes)
- .ToArray();
-
- TypeDefinition winner = null;
- var winnerPoints = -1;
-
- foreach (var t in types)
- {
- var points = 0;
- points += t.Properties.Count(p => properties.Contains((p.GetMethod?.Name ?? p.SetMethod.Name).Substring(4)));
- points += fields.Count(s => t.Fields.Any(f => f.GetSignature().ToString() == s.ToString()));
- points += methods.Count(s => t.Methods.Any(m => m.GetSignature().ToString() == s.ToString()));
-
- if (points > winnerPoints)
- {
- winnerPoints = points;
- winner = t;
- }
- else if (points == winnerPoints)
- {
- winner = null;
- }
- }
-
- if (winner != null && winnerPoints > 0)
- {
- AddType(winner);
- }
- }
-
- return result;
- }
- }
-}
diff --git a/Reactor.Greenhouse/Program.cs b/Reactor.Greenhouse/Program.cs
deleted file mode 100644
index a29a8ed..0000000
--- a/Reactor.Greenhouse/Program.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.CommandLine;
-using System.CommandLine.Invocation;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Threading.Tasks;
-using Mono.Cecil;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Serialization;
-using Reactor.Greenhouse.Setup;
-using Reactor.OxygenFilter;
-
-namespace Reactor.Greenhouse
-{
- internal static class Program
- {
- private static Task Main(string[] args)
- {
- var rootCommand = new RootCommand
- {
- new Option("steam"),
- new Option("itch"),
- };
-
- rootCommand.Handler = CommandHandler.Create(GenerateAsync);
-
- return rootCommand.InvokeAsync(args);
- }
-
- private static async Task GenerateAsync(bool steam, bool itch)
- {
- var gameManager = new GameManager();
- await gameManager.SetupAsync(steam, itch);
-
- JsonConvert.DefaultSettings = () => new JsonSerializerSettings
- {
- NullValueHandling = NullValueHandling.Ignore,
- DefaultValueHandling = DefaultValueHandling.Ignore,
- ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
- ContractResolver = ShouldSerializeContractResolver.Instance,
- };
-
- Console.WriteLine($"Generating mappings from {gameManager.PreObfuscation.Name} ({gameManager.PreObfuscation.Version})");
- using var old = ModuleDefinition.ReadModule(File.OpenRead(gameManager.PreObfuscation.Dll));
-
- if (steam)
- {
- await GenerateAsync(gameManager.Steam, old);
- }
-
- if (itch)
- {
- await GenerateAsync(gameManager.Itch, old);
- }
- }
-
- private static async Task GenerateAsync(Game game, ModuleDefinition old)
- {
- Console.WriteLine($"Compiling mappings for {game.Name} ({game.Version})");
-
- using var moduleDef = ModuleDefinition.ReadModule(File.OpenRead(game.Dll));
- var version = game.Version;
- var postfix = game.Postfix;
-
- var generated = Generator.Generate(old, moduleDef);
-
- await File.WriteAllTextAsync(Path.Combine("work", version + postfix + ".generated.json"), JsonConvert.SerializeObject(generated, Formatting.Indented));
-
- Apply(generated, Path.Combine("mappings", version + ".json"));
- Apply(generated, Path.Combine("mappings", version + postfix + ".json"));
-
- generated.Compile(moduleDef);
-
- await File.WriteAllTextAsync(Path.Combine("work", version + postfix + ".json"), JsonConvert.SerializeObject(generated));
- }
-
- private static void Apply(Mappings generated, string file)
- {
- if (File.Exists(file))
- {
- var mappings = JsonConvert.DeserializeObject(File.ReadAllText(file));
- generated.Apply(mappings);
- }
- }
-
- public class ShouldSerializeContractResolver : CamelCasePropertyNamesContractResolver
- {
- public static ShouldSerializeContractResolver Instance { get; } = new ShouldSerializeContractResolver();
-
- protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
- {
- var property = base.CreateProperty(member, memberSerialization);
-
- if (property.PropertyType != null && property.PropertyType != typeof(string))
- {
- if (property.PropertyType.GetInterface(nameof(IEnumerable)) != null)
- {
- property.ShouldSerialize = instance => (instance?.GetType().GetProperty(property.UnderlyingName!)!.GetValue(instance) as IEnumerable