Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Similar like SerializeReference but works on generic property.

public interface IMyInterface<T> {}
public class MyIntObject : IMyInterface<int> {}
public class MyGenericObject<T> : IMyInterface<T> {}

public class MyMonoBehavior : MonoBehaviour
{
    [GenericSerializeReference]
    public IMyInterface<int> Value { get; set; }
}

image

Requirement

Unity3D 2020.2+ (not guaranteed to work below 2020.2)

Installation

OpenUPM: openupm add com.quabug.generic-serialize-reference

Limitations

  • Not support struct type.
  • Not support generic field.
  • Not support variance.

Costs

  • Extra time to generate IL code while building assembly
  • Extra memory space to store a generated field for each property.

How it works

AssemblyCSharp Mode

Either generate derived classes into a custom assembly named GenericSerializeReference.OverrideAssemblyCSharp or AssemblyCSharp.dll if there's no such custom assembly.

// Generate derived types into AssemblyCSharp.dll
public class MyMonoBehavior : MonoBehaviour
{
    // [GenericSerializeReference(mode: GenerateMode.AssemblyCSharp)]
    // public IMyInterface<int> Value { get; set; }

    // 1. create a field named _Value with `IBase` type
    //    which should be able to serialized by `SerializeReference` attribute
    [SerializeReference, GenericSerializeReferenceGeneratedField]
    private GenericSerializeReference.IBase _Value;
    
    // 2. inject code into property's getter and setter
    //    make sure property get value from serialized field first
    //    and setter set serialized field into null to avoid get from it next time.
    [GenericSerializeReference]
    public IMyInterface<int> Value
    {
        get
        {
            return (IMyInterface<int>) _Value ?? <Value>k__backingField;
        }
        set
        {
            <Value>k__backingField = value;
            _Value = null;
        }
    }
}

// GenericSerializeReference.OverrideAssemblyCSharp or AssemblyCSharp.dll
// 3. gather derived types of property (`IMyInterface<int>`)
//    then generate a non-generic version of those types and make them all implement `IBase` interface
namespace <GenericSerializeReference>
{
    static class IMyInterface`1<System_Int32>
    {
        class MyIntObject : global::MyIntObject, GenericSerializeReference.IBase {}
    }
}

Embed Mode

Embed generated derived classes beside the property with GenericSerializeReferenceAttribute.

// Embed into current class
public class MyMonoBehavior : MonoBehaviour
{
    // [GenericSerializeReference(mode: GenerateMode.Embed)]
    // public IMyInterface<int> Value { get; set; }

    // 1. create a field named _Value with `IBase` type
    //    which should be able to serialized by `SerializeReference` attribute
    [SerializeReference, GenericSerializeReferenceGeneratedField]
    private <Value>__generic_serialize_reference.IBase _Value;
    
    // 2. inject code into property's getter and setter
    //    make sure property get value from serialized field first
    //    and setter set serialized field into null to avoid get from it next time.
    [GenericSerializeReference]
    public IMyInterface<int> Value
    {
        get
        {
            return (IMyInterface<int>) _Value ?? <Value>k__backingField;
        }
        set
        {
            <Value>k__backingField = value;
            _Value = null;
        }
    }
    
    // 3. gather derived types of property (`IMyInterface<int>`)
    //    then generate a non-generic version of those types and make them all implement `IBase` interface
    private static class <Value>__generic_serialize_reference
    {
        public interface IBase {}
        public class MyIntObject : global::MyIntObject, IBase {}
    }

}
  • AssemblyCSharp mode: generate any type from AutoReferenced assemblies.
  • AssemblyCSharp mode with custom GenericSerializeReference.OverrideAssemblyCSharp assembly: able to control which type should be generated by choosing certain referenced assemblies.
  • Embed mode: generate any type from assemblies referenced by processed assembly.

License

MIT

Drawer modified from TextusGames's UnitySerializedReferenceUI with MIT license

About

[GenericSerializeReference] attribute to serialize generic property in Unity3D

Topics

Resources

Stars

21 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages