public static Formatter <T> GetFormatter <T>() where T : UdonSharpBehaviour
        {
            lock (emitLock)
            {
                IFormatter formatter;
                if (formatters.TryGetValue(typeof(T), out formatter))
                {
                    return((Formatter <T>)formatter);
                }

                List <FieldInfo> serializedFieldList    = new List <FieldInfo>();
                List <FieldInfo> nonSerializedFieldList = new List <FieldInfo>();

                FieldInfo[] allFields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

                foreach (FieldInfo field in allFields)
                {
                    if (field.IsDefined(typeof(CompilerGeneratedAttribute), false))
                    {
                        continue;
                    }

                    if ((field.IsPublic && field.GetAttribute <System.NonSerializedAttribute>() == null) ||
                        (!field.IsPublic && field.GetAttribute <SerializeField>() != null))
                    {
                        serializedFieldList.Add(field);
                    }
                    else
                    {
                        nonSerializedFieldList.Add(field);
                    }
                }

                FieldInfo[] publicFields  = serializedFieldList.ToArray();
                FieldInfo[] privateFields = nonSerializedFieldList.ToArray();

                EmittedFormatter <T> .Init(publicFields, privateFields);

                InitializeRuntimeAssemblyBuilder();

                Dictionary <System.Type, FieldBuilder> serializerFields;

                BuildHelperType(typeof(T), publicFields, privateFields, out serializerFields);

                System.Type     formatterType = typeof(EmittedFormatter <>).MakeGenericType(typeof(T));
                System.Delegate readDel, writeDel;

                // Read
                {
                    System.Type   readDelegateType = typeof(ReadDataMethodDelegate <>).MakeGenericType(typeof(T));
                    MethodInfo    readDataMethod   = formatterType.GetMethods(Flags.InstancePublic).Where(e => e.Name == "Read" && e.GetParameters().Length == 2).First();
                    DynamicMethod readMethod       = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Read", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true);

                    foreach (ParameterInfo param in readDataMethod.GetParameters())
                    {
                        readMethod.DefineParameter(param.Position, param.Attributes, param.Name);
                    }

                    EmitReadMethod(readMethod.GetILGenerator(), typeof(T), publicFields, privateFields, serializerFields);

                    readDel = readMethod.CreateDelegate(readDelegateType);
                }

                // Write
                {
                    System.Type   writeDelegateType = typeof(WriteDataMethodDelegate <>).MakeGenericType(typeof(T));
                    MethodInfo    writeDataMethod   = formatterType.GetMethods(Flags.InstancePublic).Where(e => e.Name == "Write" && e.GetParameters().Length == 2).First();
                    DynamicMethod writeMethod       = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Write", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true);

                    foreach (ParameterInfo param in writeDataMethod.GetParameters())
                    {
                        writeMethod.DefineParameter(param.Position, param.Attributes, param.Name);
                    }

                    EmitWriteMethod(writeMethod.GetILGenerator(), typeof(T), publicFields, privateFields, serializerFields);

                    writeDel = writeMethod.CreateDelegate(writeDelegateType);
                }

                formatter = (Formatter <T>)System.Activator.CreateInstance(typeof(EmittedFormatter <T>), readDel, writeDel);

                formatters.Add(typeof(T), formatter);
                return((Formatter <T>)formatter);
            }
        }
Esempio n. 2
0
        public static Formatter <T> GetFormatter <T>() where T : UdonSharpBehaviour
        {
            lock (_emitLock)
            {
                if (_formatters.TryGetValue(typeof(T), out IFormatter formatter))
                {
                    return((Formatter <T>)formatter);
                }

                List <FieldInfo> serializedFieldList    = new List <FieldInfo>();
                List <FieldInfo> nonSerializedFieldList = new List <FieldInfo>();

                Stack <Type> baseTypes = new Stack <Type>();

                Type currentType = typeof(T);

                while (currentType != null &&
                       currentType != typeof(UdonSharpBehaviour))
                {
                    baseTypes.Push(currentType);
                    currentType = currentType.BaseType;
                }

                List <FieldInfo> allFields = new List <FieldInfo>();

                while (baseTypes.Count > 0)
                {
                    currentType = baseTypes.Pop();
                    allFields.AddRange(currentType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
                }

                foreach (FieldInfo field in allFields)
                {
                    // if (field.IsDefined(typeof(CompilerGeneratedAttribute), false))
                    //     continue;

                    if (FieldSymbol.IsFieldSerialized(field))
                    {
                        serializedFieldList.Add(field);
                    }
                    else
                    {
                        nonSerializedFieldList.Add(field);
                    }
                }

                FieldInfo[] publicFields  = serializedFieldList.ToArray();
                FieldInfo[] privateFields = nonSerializedFieldList.ToArray();

                EmittedFormatter <T> .Init(publicFields, privateFields);

                InitializeRuntimeAssemblyBuilder();

                BuildHelperType(typeof(T), publicFields, privateFields, out var serializerFields);

                Type     formatterType = typeof(EmittedFormatter <>).MakeGenericType(typeof(T));
                Delegate readDel, writeDel;

                // Read
                {
                    Type          readDelegateType = typeof(ReadDataMethodDelegate <>).MakeGenericType(typeof(T));
                    MethodInfo    readDataMethod   = formatterType.GetMethods(Flags.InstancePublic).First(e => e.Name == "Read" && e.GetParameters().Length == 2);
                    DynamicMethod readMethod       = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Read", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true);

                    foreach (ParameterInfo param in readDataMethod.GetParameters())
                    {
                        readMethod.DefineParameter(param.Position, param.Attributes, param.Name);
                    }

                    EmitReadMethod(readMethod.GetILGenerator(), publicFields, privateFields, serializerFields);

                    readDel = readMethod.CreateDelegate(readDelegateType);
                }

                // Write
                {
                    Type          writeDelegateType = typeof(WriteDataMethodDelegate <>).MakeGenericType(typeof(T));
                    MethodInfo    writeDataMethod   = formatterType.GetMethods(Flags.InstancePublic).First(e => e.Name == "Write" && e.GetParameters().Length == 2);
                    DynamicMethod writeMethod       = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Write", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true);

                    foreach (ParameterInfo param in writeDataMethod.GetParameters())
                    {
                        writeMethod.DefineParameter(param.Position, param.Attributes, param.Name);
                    }

                    EmitWriteMethod(writeMethod.GetILGenerator(), publicFields, privateFields, serializerFields);

                    writeDel = writeMethod.CreateDelegate(writeDelegateType);
                }

                formatter = (Formatter <T>)Activator.CreateInstance(typeof(EmittedFormatter <T>), readDel, writeDel);

                _formatters.Add(typeof(T), formatter);
                return((Formatter <T>)formatter);
            }
        }