// // /*=============================================================================== // // Copyright (C) 2025 PhantomsXR Ltd. All Rights Reserved. // // // // This file is part of the Phantom.XRMOD.UnityFusion.Runtime.CodeHook. // // // // The QuestPlatform cannot be copied, distributed, or made available to // // third-parties for commercial purposes without written permission of PhantomsXR Ltd. // // // // Contact info@phantomsxr.com for licensing requests. // // ===============================================================================*/ using System; using System.Reflection; using System.Threading.Tasks; using Phantom.XRMOD.Core.Runtime; using UnityEngine; using UnityEngine.Assertions; using UnityFusion.Runtime.Enviorment; namespace Phantom.XRMOD.UnityFusion.Runtime.CodeHook { /// /// Default implementation of . /// Uses a factory to get specific handlers for each field type in /// and injects the processed values into the target ILRuntime/CLR instance. /// public class DataBinding : IDataBinder { private readonly RuntimeFieldHandlerFactory runtimeFieldHandlerFactory = new(new DbAssetProvider()); /// /// Processes the fields in and injects their values into the associated CLR instance. /// /// The data container containing the target instance and field metadata. public void BindData(MonoData _data) { if (_data.Fields.Count == 0) { _data.BoundData = true; return; } // This logic is now self-contained within this method. Assert.IsNotNull(_data.ClrInstance, $"CLR Instance on {_data.ClassName} is null."); Assert.IsNotNull(_data.ClassType, $"Class Type on {_data.ClassName} is null."); foreach (MonoField tmp_MonoField in _data.Fields) { var tmp_RuntimeTypeHandler = runtimeFieldHandlerFactory.Get(tmp_MonoField.FieldType); if (tmp_RuntimeTypeHandler == null || tmp_RuntimeTypeHandler.GetType() == typeof(UnSupportHandler)) { Debug.LogWarning($"No handler found for field type: {tmp_MonoField.FieldType}"); continue; } var tmp_Data = tmp_RuntimeTypeHandler.ProcessValue(tmp_MonoField, _data, _data.ClassType); if (tmp_Data != null && _data.BoundData) { MakeSureValue(_data.ClassType, tmp_MonoField, tmp_Data, _data.ClrInstance); } } } private void MakeSureValue(Type _type, MonoField _field, object _value, CrossBindingAdaptorType _target) { var tmp_FieldInfo = _type.GetField(_field.FieldName, Utility.CONST_ALL_BINDING_FLAGS); if (tmp_FieldInfo != null && _value != null) { if (_field.FieldType == MonoField.FieldTypeEnum.DataProperty) { var tmp_DeserializedDataPropertyMethod = _type.GetMethod( $"DeserializedDataProperty_{_field.FieldName}", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (tmp_DeserializedDataPropertyMethod == null) return; var tmp_Result = tmp_DeserializedDataPropertyMethod.Invoke(_target.ILInstance, new object[] {_value}); var tmp_FieldOfInstance = _type.GetField(_field.FieldName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic); if (tmp_FieldOfInstance == null || !tmp_FieldOfInstance.IsDefined(typeof(DataPropertyAttribute), true)) return; if (!tmp_FieldOfInstance.IsPublic && !tmp_FieldOfInstance.IsDefined(typeof(SerializeField), true)) return; tmp_FieldOfInstance.SetValue(_target.ILInstance, tmp_Result); } else { MakeSureValueFactory.MakeSureValue(ref tmp_FieldInfo, _target.ILInstance, _value); } } else { var tmp_PropertyInfo = _type.GetProperty(_field.FieldName, Utility.CONST_ALL_BINDING_FLAGS); if (tmp_PropertyInfo != null) { tmp_PropertyInfo.SetValue(_target.ILInstance, _value); } else { string tmp_ClassPath = $"{_target.ILInstance.Type.FullName}"; Debug.LogWarning( $"[Convert Error]: Could not find a writable field or property named '{_field.FieldName}' on class '{tmp_ClassPath}'. Data may be lost."); } } } } }