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); } }
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); } }