The Issue
I had this issue when I was writing the serialization for my game framework/engine thingy I've been working for a while. the engine does not depend on any concrete type so I just get the type I'm supposed to create with reflection from the serialized YAML text and assign the serialized fields/properties. No issue everything works great so far!
Then I wanted to give it a legit test, treat it like how I would if I wanted to use this like an engine where I store the game in a serialized format then load it during runtime.
string savePath = Path.Combine(Directory.GetCurrentDirectory(), "Universe.yaml");
string saveYaml = File.ReadAllText(savePath);
Universe = Serializer.Deserialize<IUniverse>(saveYaml);Removed all the old code that sets up the scene manually, read the text from the yaml file, seriali- boom!

The Investigation
So I am assuming types are being removed because they're not referenced anywhere in the code itself. Which turned out to be partially true when I tried add the line bellow to my main method and I got a working build.
IPhysicsEngine2D test = null!;The entire physics engine project's contents are not being loaded when I don't reference any type in it. Which I consider weird because I'm not referencing my other library project which contains systems built on top of my Core library such as tweening, timers, state machines etc. either, but they are found by my assembly lookup.
What came to my mind at first was trimming, but soon I learned this is not the problem because even after disabling it I still had the same issue.
After that when I checked my output directory. I saw the binaries for my physics library there. Looking into it with ILSpy, all of my types are there so they were not being removed from the build. That just means the whole assembly just never loaded in the first place!
Indeed when I try this;
string assemblyPath = Path.Combine(Directory.GetCurrentDirectory(), "Engine.Physics2D.dll");
byte[] rawAssembly = File.ReadAllBytes(assemblyPath);
AppDomain.CurrentDomain.Load(rawAssembly);No issues again!
--Some time later--
Well, I am actually writing this as I try to find an elegant fix. But I was using IPhysicsEngine2D test = null!; method as a workaround while I worked on the engine. But when I got a Release build I notice this doesn't work again. The manual assembly loading method is still working as it should tho.
So... I remember seeing somewhere that people suggested writing a sort of preserver method where inside you just create an instance of the types you want to be preserved. Which looked like an awful way of doing it but I wanted to see how it would be like. So my structure of the engine at the time of writing is like so;
Engine/
├── Engine/
├── Engine.Core/
├── Engine.Physics2D/
├── Engine.Systems/
└── Engine.Serializers/
└── Engine.Serializers.Yaml/So what I was supposed to is adding something like so-
Engine/
├── Engine/
│ └──Preserver.cs
├── Engine.Core/
│ └──Preserver.cs
├── Engine.Physics2D/
│ └──Preserver.cs
├── Engine.Systems/
│ └──Preserver.cs
└── Engine.Serializers/
└── Engine.Serializers.Yaml/
└──Preserver.csSo as my Engine/Engine/ (which annoys me how bad it looks because I call my engine Syntriax.Engine, bad naming) project is a sort an aggregator project so I can just reference that and not all other projects, I decided to add the preserver method in it, and it calls all the other projects' preserver methods.
namespace Syntriax.Engine
{
public static class Preserver
{
public static void Preserve()
{
Core.Preserver.Preserve();
Physics2D.Preserver.Preserve();
Systems.Preserver.Preserve();
}
}
}namespace Syntriax.Engine.Physics2D
{
public static class Preserver
{
public static void Preserve()
{
#pragma warning disable CS0219 // Variable is assigned but its value is never used
PhysicsEngine2D physicsEngine2D = null!;
#pragma warning restore CS0219 // Variable is assigned but its value is never used
}
}
}But then I question do I even need to put anything in there? Because if I am calling the method, then the assembly must already be loaded so, I test it with;
namespace Syntriax.Engine.Physics2D
{
public static class Preserver
{
public static void Preserve() { }
}
}
Yea, it works. My game loads up perfectly but now I have 5 pretty much meaningless code and it will increase with each new project, and I really don't like that. In my `Engine/Engine/Preserve.cs` I could've done this;
namespace Syntriax.Engine
{
public static class Preserver
{
public static void Preserve()
{
Core.Universe universe = new();
Physics2D.PhysicsEngine2D physicsEngine2D = new();
Systems.Time.TimerBehaviour timerBehaviour = new();
}
}
}But this just creating junk for the garbage collector to collect later on, I don't like this either. I would rather not have to do any of this. If I referenced a project/assembly that means I need it and I expect it to be loaded without any further step.
My current solution
So I got a bit distracted once I got it working and I've been working on other parts of the project. Even tho I don't like it at all, I'm currently going with the empty preserver methods way of;
namespace Syntriax.Engine
{
public static class Preserver
{
public static void Preserve()
{
Core.Preserver.Preserve();
Physics2D.Preserver.Preserve();
Systems.Preserver.Preserve();
}
}
}namespace Syntriax.Engine.Physics2D
{
public static class Preserver
{
public static void Preserve() { }
}
}
I really don't like it, but at least it I can get a build and run without issues. I'll update here if/when I find a better solution that doesn't involve... any of this bs.