How to serialize and deserialize components at runtime?

Hello.

I’m working on a dynamic loading system, and need to serialize and deserialize components in the editor and in the runtime.
In the editor, it is easy as there are some classes available, but they aren’t available in the runtime.

My aproach was to find all public fields as well as the nonpublic fields where a “SerializeField” attribute is applied to. Then I would serialize those fields with the XMLSerializer.

The problem is, I don’t get the fields from any components other than my own.

The code I use to serialize a component:

public class ComponentContent
{
    public List<FieldContainer> fields;

    public Type componentType;

    // Serializes the component with all it's fields
    public static ComponentContent SerializeComponent(Component component)
    {
        var cc = new ComponentContent();
        var type = component.GetType();
        cc.componentType = type;

        // By using this code, fields is an empty array by most components
        var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic);
        
        foreach (var field in fields)
        {
            // Only use public fields or fields with a SerializeField attribute
            if (field.IsPublic || field.IsDefined(typeof(SerializeField), true))
            {
                cc.fields.Add(FieldContainer.SerializeField(field.GetValue(component), field.Name));
            }
        }

        return cc;
    }

    public Component DeserializeComponent()
    {
        // Not yet implemented
        return null;
    }
}

And the code to serialize a field and store it’s values:

public class FieldContainer
{
    public string fieldName;

    public Type fieldType;

    public string fieldValue;

    // Serializes the value of the field and returns a setup FieldContainer
    public static FieldContainer SerializeField(object obj, string fieldName)
    {
        var fc = new FieldContainer();
        Type type = obj.GetType();

        // Serializes the field using XmlSerializer
        var xmlSerializer = new XmlSerializer(type);
        using (var textWriter = new StringWriter())
        {
            xmlSerializer.Serialize(textWriter, obj);
            fc.fieldValue = textWriter.ToString();
        }

        fc.fieldType = type;
        fc.fieldName = fieldName;

        return fc;
    }

    // Returns the deserialized value of the field
    public object DeserializeField()
    {
        // Deserializes the stored data to the field value using XmlSerializer
        var xmlSerializer = new XmlSerializer(this.fieldType);
        using (var textReader = new StringReader(this.fieldValue))
        {
            return xmlSerializer.Deserialize(textReader);
        }
    }
}

Can somebody tell me, why I don’t get the fields in most components (In the first script)?

Greetings
Chillersanim

You need to add BindingFlags.Instance.

var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

EDIT:

The bindings above, do get you the fields you want (if any) - but it seems that UE.Component and many others (Transform, MonoBehaviour, etc) don’t have any fields, they’re just auto-properties which the compiler turn into set_xxx and get_xxx

If I were to make a serialization system, I’d probably let the [de]serialization of UEObjects to Unity and handle myself what Unity can’t, pretty much like Full Inspector.