Search code examples
c#.netdeserializationgame-enginegame-development

How to automatically call constructor by type name without reflection in C#?


I'm currently writing a game from scratch in C# (.NET 7) and I would like to automate mapping data to script constructors without reflection (because of Native AOT).

I already have a way to serialize and de-serialize the class fields themselves, but I'm lost when it comes to actually determining which object type to create when reading in a block of data, like e.g. Unity when it has to bind YAML data to a Component as part of an Entity.

In my eyes the most naive approach would be to have a type ID at the start of each data block and a switch statement that calls the constructor of the type with that ID as the name, like this:

public static IAsset Instantiate(string id, byte[] data)
{
    switch (id)
    {
        case "Player": return new Player(data);
        case "Vehicle": return new Vehicle(data);
        case "Weapon": return new Weapon(data);
        default: throw new ArgumentException();
    }
}

This would be fine if the amount of available asset types were very low, but I'm assuming there's going to be a ton of different scripts down the line.

Is there any way this can be done automatically for every script at compile or run time?


Solution

  • You could use a lookup table (i.e. a dictionary of delegates).

    static readonly List<string,Func<byte[],IAsset>> _masterList = new List<string,Func<byte[],IAsset>>
    {
        { "Player", x => new Player(x) },
        { "Vehicle", x => new Vehicle(x) },
        { "Weapon", x => new Weapon(x) }
    };
    
    public static IAsset Instantiate(string id, byte[] data)
    {
       if (!_masterList.ContainsKey(id)) throw new ArgumentException("Invalid ID");
       return _masterList[id](data);
    }