Decompiled source of VoidPouch v1.3.0
BepInEx/plugins/VoidPouch.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
#define DEBUG using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using BepInEx; using HarmonyLib; using SQLite; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Localization.Settings; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("VoidPouch")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("VoidPouch")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("283868D3-098F-45B8-8765-597AD223EB42")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] public class BagHook : BaseUnityPlugin { [HarmonyPatch(typeof(PlayerInventory))] [HarmonyPatch("CheckBag")] [HarmonyPostfix] public static void CheckBag(PlayerInventory __instance) { VoidPouch.playerInventory = __instance; } [HarmonyPatch(typeof(PlayerInventory))] [HarmonyPatch("HandleDrop")] [HarmonyPostfix] public static void HandleDrop(PlayerInventory __instance) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) if (((ButtonControl)Keyboard.current.cKey).wasPressedThisFrame) { if (VoidPouch.playerInventory == null) { VoidPouch.playerInventory = __instance; } if (__instance.slots[__instance.currentSlot.Value].itemId != -1) { LanVoidPouch lanVoidPouch = new LanVoidPouch(VoidPouch.slotName, VoidPouch.mapName, __instance.slots[__instance.currentSlot.Value].itemId, __instance.slots[__instance.currentSlot.Value].amount, __instance.slots[__instance.currentSlot.Value].cost, __instance.slots[__instance.currentSlot.Value].dayCounter, IsSave: false, deleted: false); lanVoidPouch.Insert(VoidPouch.connection); __instance.slots[__instance.currentSlot.Value] = new InventorySlot { itemId = -1L, amount = -1, cost = -1, dayCounter = -1 }; } } } [HarmonyPatch(typeof(GameManager))] [HarmonyPatch("OnDayChanged")] [HarmonyPostfix] public static void OnDayChanged(GameManager __instance) { LanVoidPouch.Save(VoidPouch.connection, VoidPouch.slotName, VoidPouch.mapName); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerInteraction), "Update")] public static void PlayerInteraction_Update_Postfix(PlayerInteraction __instance) { if (GameManager.Instance != null && Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame && ((Object)(object)VoidPouch._myVoidPanel == (Object)null || !VoidPouch._myVoidPanel.activeSelf) && !Cursor.visible) { AttemptDeleteItem(__instance); } } private static void AttemptDeleteItem(PlayerInteraction playerInteraction) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return; } FieldInfo field = typeof(PlayerInteraction).GetField("isInteractionEnabled", BindingFlags.Instance | BindingFlags.NonPublic); if (!(bool)field.GetValue(playerInteraction)) { return; } Ray val = main.ViewportPointToRay(Vector3.one / 2f); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, ref val2, playerInteraction.interactionDistance, LayerMask.op_Implicit(playerInteraction.layerMask), (QueryTriggerInteraction)1)) { Item componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Item>(); if ((Object)(object)componentInParent != (Object)null && ((Interactable)componentInParent).CanInteract()) { ExecuteItemDeletion(componentInParent); } } } private static void ExecuteItemDeletion(Item item) { LanVoidPouch lanVoidPouch = new LanVoidPouch(VoidPouch.slotName, VoidPouch.mapName, item.itemSO.id, item.amount.Value, item.cost, item.dayCounter.Value, IsSave: false, deleted: false); lanVoidPouch.Insert(VoidPouch.connection); ((Component)item).gameObject.SetActive(false); if ((Object)(object)((NetworkBehaviour)item).NetworkObject != (Object)null) { ((NetworkBehaviour)item).NetworkObject.Despawn(true); } } } public class CustomButton : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { public Image image; public TextMeshProUGUI textSubtitle; public TextMeshProUGUI textAmount; private int lanVoidPouchId; private long itemSoId; private string localName; private int number; private TextMeshProUGUI _targetInfoText; public void SetData(int lanVoidPouchId, long itemSoId, int amount, string localName, int number, TextMeshProUGUI infoText) { this.lanVoidPouchId = lanVoidPouchId; this.itemSoId = itemSoId; _targetInfoText = infoText; this.localName = localName; this.number = number; if ((Object)(object)textAmount != (Object)null) { ((TMP_Text)textAmount).text = amount.ToString(); } } public void OnPointerEnter(PointerEventData eventData) { if ((Object)(object)_targetInfoText != (Object)null) { ((TMP_Text)_targetInfoText).text = $"{localName}: {number}"; } } public void OnPointerExit(PointerEventData eventData) { if ((Object)(object)_targetInfoText != (Object)null) { ((TMP_Text)_targetInfoText).text = ""; } } } public class LanVoidPouch { [PrimaryKey] [AutoIncrement] [Column("id")] public int Id { get; set; } [NotNull] [Column("saveName")] public string SaveName { get; set; } [NotNull] [Column("mapName")] public string MapName { get; set; } [NotNull] [Column("itemsoId")] public long ItemsoId { get; set; } [NotNull] [Column("amount")] public int Amount { get; set; } [NotNull] [Column("cost")] public int Cost { get; set; } [NotNull] [Column("dayCounter")] public int DayCounter { get; set; } [NotNull] [Column("isSave")] public bool IsSave { get; set; } [NotNull] [Column("Deleted")] public bool Deleted { get; set; } public LanVoidPouch() { } public LanVoidPouch(string saveName, string mapName, long itemsoId, int amount, int cost, int dayCounter, bool IsSave, bool deleted) { SaveName = saveName; MapName = mapName; ItemsoId = itemsoId; Amount = amount; Cost = cost; DayCounter = dayCounter; this.IsSave = IsSave; Deleted = deleted; } public long Insert(SQLiteConnection connection) { return connection.Execute("INSERT INTO LanVoidPouch (SaveName, MapName, ItemsoId, Amount, Cost, DayCounter, IsSave, Deleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", SaveName, MapName, ItemsoId, Amount, Cost, DayCounter, IsSave, Deleted); } public void Delete(SQLiteConnection connection) { connection.Execute("UPDATE LanVoidPouch SET Deleted = 1 , isSave = 0 WHERE Id = ?", Id); } public static void Save(SQLiteConnection connection, string saveName, string mapName) { connection.Execute("UPDATE LanVoidPouch SET IsSave = TRUE WHERE SaveName = ? AND MapName = ?", saveName, mapName); connection.Execute("DELETE FROM LanVoidPouch WHERE SaveName = ? AND MapName = ? AND Deleted = TRUE", saveName, mapName); } public static void DeleteNotSave(SQLiteConnection connection, string saveName, string mapName) { connection.Execute("UPDATE LanVoidPouch SET IsSave = TRUE, Deleted = FALSE WHERE SaveName = ? AND MapName = ? AND Deleted = TRUE", saveName, mapName); connection.Execute("DELETE FROM LanVoidPouch WHERE SaveName = ? AND MapName = ? AND IsSave = 0", saveName, mapName); } public static List<LanVoidPouch> FindBySaveNameAndMapName(SQLiteConnection connection, string saveName, string mapName) { return connection.Query<LanVoidPouch>("SELECT * FROM LanVoidPouch WHERE SaveName = ? AND MapName = ? AND Deleted = 0 ORDER BY ItemsoId", new object[2] { saveName, mapName }); } public static List<LanVoidPouch> FindBySaveNameAndMapNameAndItemSoId(SQLiteConnection connection, string saveName, string mapName, long itemSoId) { return connection.Query<LanVoidPouch>("SELECT * FROM LanVoidPouch WHERE SaveName = ? AND MapName = ? AND ItemsoId = ? AND Deleted = 0", new object[3] { saveName, mapName, itemSoId }); } public static LanVoidPouch HasItemInSlot(SQLiteConnection connection, string saveName, string mapName, int slot) { return connection.Query<LanVoidPouch>("SELECT * FROM LanVoidPouch WHERE SaveName = ? AND MapName = ? AND Slot = ? AND Deleted = 0 ORDER BY Amount ASC", new object[3] { saveName, mapName, slot }).FirstOrDefault(); } public static void DecreaseItemInSlot(SQLiteConnection connection, string saveName, string mapName, int itemSoId) { List<LanVoidPouch> list = connection.Query<LanVoidPouch>("SELECT * FROM LanVoidPouch WHERE SaveName = ? AND MapName = ? AND itemsoId = ? AND Deleted = 0 ORDER BY Amount ASC", new object[3] { saveName, mapName, itemSoId }); if (list.Count > 0) { LanVoidPouch lanVoidPouch = list[0]; if (lanVoidPouch.Amount == 1) { lanVoidPouch.Delete(connection); return; } lanVoidPouch.Delete(connection); connection.Insert(new LanVoidPouch(saveName, mapName, itemSoId, lanVoidPouch.Amount - 1, lanVoidPouch.Cost, lanVoidPouch.DayCounter, IsSave: false, deleted: false)); } } public static int GetItemAmountInSlot(SQLiteConnection connection, string saveName, string mapName, long itemSoId) { List<LanVoidPouch> list = connection.Query<LanVoidPouch>("SELECT * FROM LanVoidPouch WHERE SaveName = ? AND MapName = ? AND ItemsoId = ? AND Deleted = 0", new object[3] { saveName, mapName, itemSoId }); ItemSO itemById = GameManager.Instance.GetItemById(itemSoId); if (itemById.amount > 0) { int num = 0; foreach (LanVoidPouch item in list) { num += item.Amount; } return num; } return list.Sum((LanVoidPouch lanVoidPouch) => lanVoidPouch.Amount); } } public class RestockHook : BaseUnityPlugin { [HarmonyPrefix] [HarmonyPatch(typeof(RestockerWait), "OnUpdate")] public static bool OnUpdate(RestockerWait __instance) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)GameManager.Instance).IsHost) { return true; } FieldInfo field = typeof(RestockerWait).GetField("rc", BindingFlags.Instance | BindingFlags.NonPublic); RestockerController val = (RestockerController)field.GetValue(__instance); if (val.HasReachedDestination(1f)) { val.agent.isStopped = true; val.ChangeAnimationState(__instance.idleAnimation, 0.05f); ((Component)val).transform.rotation = Quaternion.Slerp(((Component)val).transform.rotation, val.GetInitialRotation(), 5f * Time.deltaTime); } FieldInfo field2 = typeof(RestockerWait).GetField("timer", BindingFlags.Instance | BindingFlags.NonPublic); float num = (float)field2.GetValue(__instance); num += Time.deltaTime; field2.SetValue(__instance, num); if (num < __instance.waitTime) { return false; } if (!FindItemToRestock(__instance)) { field2.SetValue(__instance, 0f); if ((double)Vector3.Distance(((Component)val).transform.position, val.GetInitialPosition()) <= 1.0) { return false; } val.agent.isStopped = false; val.GoToStartPosition(); val.ChangeAnimationState(__instance.walkAnimation, 0.05f); } return false; } public static bool FindItemToRestock(RestockerWait __instance) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) FieldInfo field = typeof(RestockerWait).GetField("rc", BindingFlags.Instance | BindingFlags.NonPublic); RestockerController rc = (RestockerController)field.GetValue(__instance); foreach (Item item2 in (from x in Object.FindObjectsOfType<Item>() where x.onStand.Value && x.amount.Value <= 0 && !x.IsRestockTarget() select x into go orderby Vector3.Distance(((Component)go).transform.position, ((Component)rc).transform.position) select go).ToList()) { Item item = item2; List<LanVoidPouch> list = LanVoidPouch.FindBySaveNameAndMapNameAndItemSoId(VoidPouch.connection, VoidPouch.slotName, VoidPouch.mapName, item.itemSO.id); if (list != null && list.Count > 0) { FieldInfo field2 = typeof(RestockerController).GetField("inventorySlot", BindingFlags.Instance | BindingFlags.NonPublic); NetworkVariable<InventorySlot> val = (NetworkVariable<InventorySlot>)field2.GetValue(rc); val.Value = new InventorySlot { itemId = list[0].ItemsoId, amount = list[0].Amount, cost = list[0].Cost, dayCounter = list[0].DayCounter }; list[0].Delete(VoidPouch.connection); Item val2 = Object.FindAnyObjectByType<Item>(); rc.SetItems(item, val2); rc.SetDestination(((Component)rc.targetItem).transform); rc.ChangeState(rc.stateRestockTarget); return true; } List<Item> list2 = (from x in Object.FindObjectsOfType<Item>() where (Object)(object)x.itemSO == (Object)(object)item.itemSO && x.IsInFreezer() && x.amount.Value > 0 && !x.IsRestockSource() select x into go orderby Vector3.Distance(((Component)go).transform.position, ((Component)rc).transform.position) select go).ToList(); if (list2.Count > 0) { rc.SetItems(item, list2[0]); rc.SetDestination(((Component)rc.sourceItem).transform); rc.ChangeState(__instance.stateTakeSource); return true; } } return false; } } [BepInPlugin("com.lan.VoidPouch", "储物魂导器", "1.3.0")] public class VoidPouch : BaseUnityPlugin { public class Listen : MonoBehaviour { private void Update() { if (GameManager.Instance == null || UIManager.Instance == null) { return; } bool flag = (Object)(object)_myVoidPanel != (Object)null && _myVoidPanel.activeSelf; if (flag && ((ButtonControl)Keyboard.current.escapeKey).wasPressedThisFrame) { HidePanel(); return; } if (((ButtonControl)Keyboard.current.bKey).wasPressedThisFrame) { if (!flag) { mouseIsShow = Cursor.visible; ui(); Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } else { HidePanel(); } } if (Mouse.current != null && Mouse.current.backButton.wasPressedThisFrame) { if (!flag) { mouseIsShow = Cursor.visible; ui(); Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } else { HidePanel(); } } if (Mouse.current != null && Mouse.current.rightButton.wasPressedThisFrame && flag) { HidePanel(); } } public static void HidePanel() { if ((Object)(object)_myVoidPanel != (Object)null && _myVoidPanel.activeSelf) { _myVoidPanel.SetActive(false); ((Behaviour)playerInventory).enabled = true; if (!mouseIsShow) { Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } } if (!_myVoidPanel.activeSelf) { ((Behaviour)playerInventory).enabled = true; if (!mouseIsShow) { Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } } } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__10_0; public static Func<LanVoidPouch, int> <>9__10_4; internal void <ui>b__10_0() { ((Behaviour)playerInventory).enabled = true; if (!mouseIsShow) { Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } } internal int <ui>b__10_4(LanVoidPouch x) { return x.Amount; } } public static PlayerInventory playerInventory; public static string mapName; public static string slotName; public static string dbPath; public static SQLiteConnection connection; public static GameObject _myVoidPanel; private static Transform _myListContainer; public static bool mouseIsShow; private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown Harmony val = new Harmony("com.lan.VoidPouch"); val.PatchAll(); val.PatchAll(typeof(BagHook)); val.PatchAll(typeof(RestockHook)); string directoryName = Path.GetDirectoryName(Application.dataPath); dbPath = Path.Combine(directoryName, "lan.mod.db"); if (!File.Exists(dbPath)) { using (File.Create(dbPath)) { } Debug.Log((object)("数据库文件已创建: " + dbPath)); } try { connection = new SQLiteConnection(dbPath); connection.CreateTable<LanVoidPouch>(); } catch (Exception ex) { Debug.LogError((object)("数据库连接失败,请下载前置Mod:https://thunderstore.io/c/old-market-simulator/p/Lan/WheelchairRanch" + ex.Message)); throw; } SceneManager.sceneLoaded += OnSceneLoaded; GameObject val2 = new GameObject("Listen"); ((Object)val2).hideFlags = (HideFlags)61; val2.AddComponent<Listen>(); Debug.LogWarning((object)"储物魂导器加载完成 --作者:她说缝上都不给我"); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (GameManager.Instance != null) { FieldInfo field = ((object)SaveManager.Instance).GetType().GetField("currentSlot", BindingFlags.Instance | BindingFlags.NonPublic); slotName = field.GetValue(SaveManager.Instance).ToString(); Scene activeScene = SceneManager.GetActiveScene(); mapName = ((Scene)(ref activeScene)).name; LanVoidPouch.DeleteNotSave(connection, slotName, mapName); } } public static void ui() { //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Expected O, but got Unknown //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Expected O, but got Unknown //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Expected O, but got Unknown //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Expected O, but got Unknown //IL_04a7: Unknown result type (might be due to invalid IL or missing references) //IL_04b4: Unknown result type (might be due to invalid IL or missing references) //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Unknown result type (might be due to invalid IL or missing references) //IL_05fd: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown if ((Object)(object)_myVoidPanel == (Object)null) { _myVoidPanel = Object.Instantiate<GameObject>(UIManager.Instance.panelDockOrders, UIManager.Instance.panelDockOrders.transform.parent); ((Object)_myVoidPanel).name = "Panel_VoidPouch"; MonoBehaviour[] components = _myVoidPanel.GetComponents<MonoBehaviour>(); MonoBehaviour[] array = components; foreach (MonoBehaviour val in array) { Type type = ((object)val).GetType(); string @namespace = type.Namespace; if (@namespace == null || (!@namespace.StartsWith("UnityEngine") && !@namespace.StartsWith("TMPro"))) { Object.DestroyImmediate((Object)(object)val); } } string transformPath = GetTransformPath(((Component)UIManager.Instance.listDockOrders).transform, UIManager.Instance.panelDockOrders.transform); _myListContainer = _myVoidPanel.transform.Find(transformPath); if ((Object)(object)_myListContainer == (Object)null) { VerticalLayoutGroup componentInChildren = _myVoidPanel.GetComponentInChildren<VerticalLayoutGroup>(); object obj = ((componentInChildren != null) ? ((Component)componentInChildren).transform : null); if (obj == null) { GridLayoutGroup componentInChildren2 = _myVoidPanel.GetComponentInChildren<GridLayoutGroup>(); obj = ((componentInChildren2 != null) ? ((Component)componentInChildren2).transform : null); } _myListContainer = (Transform)obj; } Button[] componentsInChildren = _myVoidPanel.GetComponentsInChildren<Button>(true); Button[] array2 = componentsInChildren; foreach (Button val2 in array2) { if (!(((Object)val2).name == "ButtonClose")) { continue; } ButtonClickedEvent onClick = val2.onClick; object obj2 = <>c.<>9__10_0; if (obj2 == null) { UnityAction val3 = delegate { ((Behaviour)playerInventory).enabled = true; if (!mouseIsShow) { Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } }; <>c.<>9__10_0 = val3; obj2 = (object)val3; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); break; } } GridLayoutGroup val4 = ((Component)_myListContainer).GetComponent<GridLayoutGroup>(); if ((Object)(object)val4 == (Object)null) { LayoutGroup[] components2 = ((Component)_myListContainer).GetComponents<LayoutGroup>(); foreach (LayoutGroup val5 in components2) { Object.DestroyImmediate((Object)(object)val5); } val4 = ((Component)_myListContainer).gameObject.AddComponent<GridLayoutGroup>(); } val4.constraint = (Constraint)1; val4.constraintCount = 10; val4.cellSize = new Vector2(90f, 90f); val4.spacing = new Vector2(8f, 8f); val4.startCorner = (Corner)0; val4.startAxis = (Axis)0; ((LayoutGroup)val4).childAlignment = (TextAnchor)4; for (int num = _myListContainer.childCount - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)((Component)_myListContainer.GetChild(num)).gameObject); } List<Button> list = new List<Button>(); List<LanVoidPouch> list2 = LanVoidPouch.FindBySaveNameAndMapName(connection, slotName, mapName); TextMeshProUGUI[] componentsInChildren2 = _myVoidPanel.GetComponentsInChildren<TextMeshProUGUI>(); TextMeshProUGUI val6 = componentsInChildren2[^2]; ((TMP_Text)val6).text = ""; ((TMP_Text)componentsInChildren2[^1]).text = ""; for (int l = 0; l < list2.Count(); l++) { LanVoidPouch item = list2[l]; ItemSO itemById = GameManager.Instance.GetItemById(item.ItemsoId); GameObject val7 = new GameObject($"CustomItem_{l}"); val7.transform.SetParent(_myListContainer, false); RectTransform val8 = val7.AddComponent<RectTransform>(); val8.pivot = new Vector2(0.5f, 0.5f); val8.sizeDelta = new Vector2(90f, 90f); Button val9 = val7.AddComponent<Button>(); GameObject val10 = new GameObject("Content"); RectTransform val11 = val10.AddComponent<RectTransform>(); ((Transform)val11).SetParent((Transform)(object)val8, false); val11.anchorMin = Vector2.zero; val11.anchorMax = Vector2.one; val11.offsetMin = new Vector2(5f, 5f); val11.offsetMax = new Vector2(-5f, -5f); GameObject val12 = new GameObject("ItemImage"); RectTransform val13 = val12.AddComponent<RectTransform>(); ((Transform)val13).SetParent((Transform)(object)val11, false); val13.anchorMin = Vector2.zero; val13.anchorMax = Vector2.one; val13.sizeDelta = Vector2.zero; val13.anchoredPosition = Vector2.zero; Image val14 = val12.AddComponent<Image>(); val14.sprite = itemById.sprite; val14.preserveAspect = true; ((Graphic)val14).raycastTarget = true; GameObject val15 = new GameObject("AmountText"); RectTransform val16 = val15.AddComponent<RectTransform>(); ((Transform)val16).SetParent((Transform)(object)val8, false); val16.anchorMin = new Vector2(0.8f, 0.8f); val16.anchorMax = Vector2.one; TextMeshProUGUI val17 = val15.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val17).text = item.Amount.ToString(); ((TMP_Text)val17).fontSize = 30f; ((TMP_Text)val17).alignment = (TextAlignmentOptions)514; ((Graphic)val17).color = Color.white; ((Graphic)val17).raycastTarget = false; CustomButton customButton = val7.AddComponent<CustomButton>(); customButton.image = val14; customButton.textAmount = val17; int num2 = 0; if (itemById.amount > 1) { num2 = list2.Where((LanVoidPouch x) => x.ItemsoId == item.ItemsoId).Count(); } else { List<LanVoidPouch> source = list2.Where((LanVoidPouch x) => x.ItemsoId == item.ItemsoId).ToList(); num2 = source.Sum((LanVoidPouch x) => x.Amount); } customButton.SetData(item.Id, itemById.id, item.Amount, itemById.GetLocalizedName(), num2, val6); ((UnityEventBase)val9.onClick).RemoveAllListeners(); ((UnityEvent)val9.onClick).AddListener((UnityAction)delegate { playerInventory.GiveItemServerRpc(item.ItemsoId, item.Amount, item.Cost, item.DayCounter); item.Delete(connection); ui(); }); list.Add(val9); } MethodInfo method = typeof(UIManager).GetMethod("SetupSmartWrappedGridNavigation", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { method.Invoke(UIManager.Instance, new object[3] { list, 10, true }); } _myVoidPanel.SetActive(true); ((Behaviour)playerInventory).enabled = false; if (((object)LocalizationSettings.SelectedLocale).ToString().Contains("Chinese")) { ((TMP_Text)componentsInChildren2[^3]).text = "点击物品可以将其取回背包"; } else { ((TMP_Text)componentsInChildren2[^3]).text = "Click on the item to put it in your backpack"; } ((TMP_Text)componentsInChildren2[^4]).text = "储物魂导器(VoidPouch)"; } private static string GetTransformPath(Transform target, Transform root) { if ((Object)(object)target == (Object)(object)root) { return ""; } string text = ((Object)target).name; while ((Object)(object)target.parent != (Object)null && (Object)(object)target.parent != (Object)(object)root) { target = target.parent; text = ((Object)target).name + "/" + text; } return text; } } namespace SQLite; public class SQLiteException : Exception { public SQLite3.Result Result { get; private set; } protected SQLiteException(SQLite3.Result r, string message) : base(message) { Result = r; } public static SQLiteException New(SQLite3.Result r, string message) { return new SQLiteException(r, message); } } public class NotNullConstraintViolationException : SQLiteException { public IEnumerable<TableMapping.Column> Columns { get; protected set; } protected NotNullConstraintViolationException(SQLite3.Result r, string message) : this(r, message, null, null) { } protected NotNullConstraintViolationException(SQLite3.Result r, string message, TableMapping mapping, object obj) : base(r, message) { if (mapping != null && obj != null) { Columns = mapping.Columns.Where((TableMapping.Column c) => !c.IsNullable && c.GetValue(obj) == null); } } public new static NotNullConstraintViolationException New(SQLite3.Result r, string message) { return new NotNullConstraintViolationException(r, message); } public static NotNullConstraintViolationException New(SQLite3.Result r, string message, TableMapping mapping, object obj) { return new NotNullConstraintViolationException(r, message, mapping, obj); } public static NotNullConstraintViolationException New(SQLiteException exception, TableMapping mapping, object obj) { return new NotNullConstraintViolationException(exception.Result, exception.Message, mapping, obj); } } [Flags] public enum SQLiteOpenFlags { ReadOnly = 1, ReadWrite = 2, Create = 4, Uri = 0x40, Memory = 0x80, NoMutex = 0x8000, FullMutex = 0x10000, SharedCache = 0x20000, PrivateCache = 0x40000, ProtectionComplete = 0x100000, ProtectionCompleteUnlessOpen = 0x200000, ProtectionCompleteUntilFirstUserAuthentication = 0x300000, ProtectionNone = 0x400000 } [Flags] public enum CreateFlags { None = 0, ImplicitPK = 1, ImplicitIndex = 2, AllImplicit = 3, AutoIncPK = 4, FullTextSearch3 = 0x100, FullTextSearch4 = 0x200 } public interface ISQLiteConnection : IDisposable { IntPtr Handle { get; } string DatabasePath { get; } int LibVersionNumber { get; } bool TimeExecution { get; set; } bool Trace { get; set; } Action<string> Tracer { get; set; } bool StoreDateTimeAsTicks { get; } bool StoreTimeSpanAsTicks { get; } string DateTimeStringFormat { get; } TimeSpan BusyTimeout { get; set; } IEnumerable<TableMapping> TableMappings { get; } bool IsInTransaction { get; } event EventHandler<NotifyTableChangedEventArgs> TableChanged; void Backup(string destinationDatabasePath, string databaseName = "main"); void BeginTransaction(); void Close(); void Commit(); SQLiteCommand CreateCommand(string cmdText, params object[] ps); SQLiteCommand CreateCommand(string cmdText, Dictionary<string, object> args); int CreateIndex(string indexName, string tableName, string[] columnNames, bool unique = false); int CreateIndex(string indexName, string tableName, string columnName, bool unique = false); int CreateIndex(string tableName, string columnName, bool unique = false); int CreateIndex(string tableName, string[] columnNames, bool unique = false); int CreateIndex<T>(Expression<Func<T, object>> property, bool unique = false); CreateTableResult CreateTable<T>(CreateFlags createFlags = CreateFlags.None); CreateTableResult CreateTable(Type ty, CreateFlags createFlags = CreateFlags.None); CreateTablesResult CreateTables<T, T2>(CreateFlags createFlags = CreateFlags.None) where T : new() where T2 : new(); CreateTablesResult CreateTables<T, T2, T3>(CreateFlags createFlags = CreateFlags.None) where T : new() where T2 : new() where T3 : new(); CreateTablesResult CreateTables<T, T2, T3, T4>(CreateFlags createFlags = CreateFlags.None) where T : new() where T2 : new() where T3 : new() where T4 : new(); CreateTablesResult CreateTables<T, T2, T3, T4, T5>(CreateFlags createFlags = CreateFlags.None) where T : new() where T2 : new() where T3 : new() where T4 : new() where T5 : new(); CreateTablesResult CreateTables(CreateFlags createFlags = CreateFlags.None, params Type[] types); IEnumerable<T> DeferredQuery<T>(string query, params object[] args) where T : new(); IEnumerable<object> DeferredQuery(TableMapping map, string query, params object[] args); int Delete(object objectToDelete); int Delete<T>(object primaryKey); int Delete(object primaryKey, TableMapping map); int DeleteAll<T>(); int DeleteAll(TableMapping map); int DropTable<T>(); int DropTable(TableMapping map); void EnableLoadExtension(bool enabled); void EnableWriteAheadLogging(); int Execute(string query, params object[] args); T ExecuteScalar<T>(string query, params object[] args); T Find<T>(object pk) where T : new(); object Find(object pk, TableMapping map); T Find<T>(Expression<Func<T, bool>> predicate) where T : new(); T FindWithQuery<T>(string query, params object[] args) where T : new(); object FindWithQuery(TableMapping map, string query, params object[] args); T Get<T>(object pk) where T : new(); object Get(object pk, TableMapping map); T Get<T>(Expression<Func<T, bool>> predicate) where T : new(); TableMapping GetMapping(Type type, CreateFlags createFlags = CreateFlags.None); TableMapping GetMapping<T>(CreateFlags createFlags = CreateFlags.None); List<SQLiteConnection.ColumnInfo> GetTableInfo(string tableName); int Insert(object obj); int Insert(object obj, Type objType); int Insert(object obj, string extra); int Insert(object obj, string extra, Type objType); int InsertAll(IEnumerable objects, bool runInTransaction = true); int InsertAll(IEnumerable objects, string extra, bool runInTransaction = true); int InsertAll(IEnumerable objects, Type objType, bool runInTransaction = true); int InsertOrReplace(object obj); int InsertOrReplace(object obj, Type objType); List<T> Query<T>(string query, params object[] args) where T : new(); List<object> Query(TableMapping map, string query, params object[] args); List<T> QueryScalars<T>(string query, params object[] args); void ReKey(string key); void ReKey(byte[] key); void Release(string savepoint); void Rollback(); void RollbackTo(string savepoint); void RunInTransaction(Action action); string SaveTransactionPoint(); TableQuery<T> Table<T>() where T : new(); int Update(object obj); int Update(object obj, Type objType); int UpdateAll(IEnumerable objects, bool runInTransaction = true); } [Preserve(AllMembers = true)] public class SQLiteConnection : ISQLiteConnection, IDisposable { private struct IndexedColumn { public int Order; public string ColumnName; } private struct IndexInfo { public string IndexName; public string TableName; public bool Unique; public List<IndexedColumn> Columns; } [Preserve(AllMembers = true)] public class ColumnInfo { [Column("name")] public string Name { get; set; } public int notnull { get; set; } public override string ToString() { return Name; } } private bool _open; private TimeSpan _busyTimeout; private static readonly Dictionary<string, TableMapping> _mappings = new Dictionary<string, TableMapping>(); private Stopwatch _sw; private long _elapsedMilliseconds = 0L; private int _transactionDepth = 0; private Random _rand = new Random(); private static readonly IntPtr NullHandle = default(IntPtr); private static readonly IntPtr NullBackupHandle = default(IntPtr); private readonly Dictionary<Tuple<string, string>, PreparedSqlLiteInsertCommand> _insertCommandMap = new Dictionary<Tuple<string, string>, PreparedSqlLiteInsertCommand>(); public IntPtr Handle { get; private set; } public string DatabasePath { get; private set; } public int LibVersionNumber { get; private set; } public bool TimeExecution { get; set; } public bool Trace { get; set; } public Action<string> Tracer { get; set; } public bool StoreDateTimeAsTicks { get; private set; } public bool StoreTimeSpanAsTicks { get; private set; } public string DateTimeStringFormat { get; private set; } internal DateTimeStyles DateTimeStyle { get; private set; } public TimeSpan BusyTimeout { get { return _busyTimeout; } set { _busyTimeout = value; if (Handle != NullHandle) { SQLite3.BusyTimeout(Handle, (int)_busyTimeout.TotalMilliseconds); } } } public IEnumerable<TableMapping> TableMappings { get { lock (_mappings) { return new List<TableMapping>(_mappings.Values); } } } public bool IsInTransaction => _transactionDepth > 0; public event EventHandler<NotifyTableChangedEventArgs> TableChanged; public SQLiteConnection(string databasePath, bool storeDateTimeAsTicks = true) : this(new SQLiteConnectionString(databasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create, storeDateTimeAsTicks)) { } public SQLiteConnection(string databasePath, SQLiteOpenFlags openFlags, bool storeDateTimeAsTicks = true) : this(new SQLiteConnectionString(databasePath, openFlags, storeDateTimeAsTicks)) { } public SQLiteConnection(SQLiteConnectionString connectionString) { if (connectionString == null) { throw new ArgumentNullException("connectionString"); } if (connectionString.DatabasePath == null) { throw new InvalidOperationException("DatabasePath must be specified"); } DatabasePath = connectionString.DatabasePath; LibVersionNumber = SQLite3.LibVersionNumber(); byte[] nullTerminatedUtf = GetNullTerminatedUtf8(connectionString.DatabasePath); IntPtr db; SQLite3.Result result = SQLite3.Open(nullTerminatedUtf, out db, (int)connectionString.OpenFlags, connectionString.VfsName); Handle = db; if (result != 0) { throw SQLiteException.New(result, $"Could not open database file: {DatabasePath} ({result})"); } _open = true; StoreDateTimeAsTicks = connectionString.StoreDateTimeAsTicks; StoreTimeSpanAsTicks = connectionString.StoreTimeSpanAsTicks; DateTimeStringFormat = connectionString.DateTimeStringFormat; DateTimeStyle = connectionString.DateTimeStyle; BusyTimeout = TimeSpan.FromSeconds(1.0); Tracer = delegate(string line) { Debug.WriteLine(line); }; connectionString.PreKeyAction?.Invoke(this); if (connectionString.Key is string key) { SetKey(key); } else if (connectionString.Key is byte[] key2) { SetKey(key2); } else if (connectionString.Key != null) { throw new InvalidOperationException("Encryption keys must be strings or byte arrays"); } connectionString.PostKeyAction?.Invoke(this); } public void EnableWriteAheadLogging() { ExecuteScalar<string>("PRAGMA journal_mode=WAL", Array.Empty<object>()); } private static string Quote(string unsafeString) { if (unsafeString == null) { return "NULL"; } string text = unsafeString.Replace("'", "''"); return "'" + text + "'"; } private void SetKey(string key) { if (key == null) { throw new ArgumentNullException("key"); } string text = Quote(key); ExecuteScalar<string>("pragma key = " + text, Array.Empty<object>()); } private void SetKey(byte[] key) { if (key == null) { throw new ArgumentNullException("key"); } if (key.Length != 32 && key.Length != 48) { throw new ArgumentException("Key must be 32 bytes (256-bit) or 48 bytes (384-bit)", "key"); } string text = string.Join("", key.Select((byte x) => x.ToString("X2"))); ExecuteScalar<string>("pragma key = \"x'" + text + "'\"", Array.Empty<object>()); } public void ReKey(string key) { if (key == null) { throw new ArgumentNullException("key"); } string text = Quote(key); ExecuteScalar<string>("pragma rekey = " + text, Array.Empty<object>()); } public void ReKey(byte[] key) { if (key == null) { throw new ArgumentNullException("key"); } if (key.Length != 32 && key.Length != 48) { throw new ArgumentException("Key must be 32 bytes (256-bit) or 48 bytes (384-bit)", "key"); } string text = string.Join("", key.Select((byte x) => x.ToString("X2"))); ExecuteScalar<string>("pragma rekey = \"x'" + text + "'\"", Array.Empty<object>()); } public void EnableLoadExtension(bool enabled) { SQLite3.Result result = SQLite3.EnableLoadExtension(Handle, enabled ? 1 : 0); if (result != 0) { string errmsg = SQLite3.GetErrmsg(Handle); throw SQLiteException.New(result, errmsg); } } private static byte[] GetNullTerminatedUtf8(string s) { int byteCount = Encoding.UTF8.GetByteCount(s); byte[] array = new byte[byteCount + 1]; byteCount = Encoding.UTF8.GetBytes(s, 0, s.Length, array, 0); return array; } public TableMapping GetMapping(Type type, CreateFlags createFlags = CreateFlags.None) { string fullName = type.FullName; TableMapping value; lock (_mappings) { if (_mappings.TryGetValue(fullName, out value)) { if (createFlags != 0 && createFlags != value.CreateFlags) { value = new TableMapping(type, createFlags); _mappings[fullName] = value; } } else { value = new TableMapping(type, createFlags); _mappings.Add(fullName, value); } } return value; } public TableMapping GetMapping<T>(CreateFlags createFlags = CreateFlags.None) { return GetMapping(typeof(T), createFlags); } public int DropTable<T>() { return DropTable(GetMapping(typeof(T))); } public int DropTable(TableMapping map) { string query = $"drop table if exists \"{map.TableName}\""; return Execute(query); } public CreateTableResult CreateTable<T>(CreateFlags createFlags = CreateFlags.None) { return CreateTable(typeof(T), createFlags); } public CreateTableResult CreateTable(Type ty, CreateFlags createFlags = CreateFlags.None) { TableMapping mapping = GetMapping(ty, createFlags); if (mapping.Columns.Length == 0) { throw new Exception($"Cannot create a table without columns (does '{ty.FullName}' have public properties?)"); } CreateTableResult result = CreateTableResult.Created; List<ColumnInfo> tableInfo = GetTableInfo(mapping.TableName); if (tableInfo.Count == 0) { bool flag = (createFlags & CreateFlags.FullTextSearch3) != 0; bool flag2 = (createFlags & CreateFlags.FullTextSearch4) != 0; string text = ((flag || flag2) ? "virtual " : string.Empty); string text2 = (flag ? "using fts3 " : (flag2 ? "using fts4 " : string.Empty)); string text3 = "create " + text + "table if not exists \"" + mapping.TableName + "\" " + text2 + "(\n"; IEnumerable<string> source = mapping.Columns.Select((TableMapping.Column p) => Orm.SqlDecl(p, StoreDateTimeAsTicks, StoreTimeSpanAsTicks)); string text4 = string.Join(",\n", source.ToArray()); text3 += text4; text3 += ")"; if (mapping.WithoutRowId) { text3 += " without rowid"; } Execute(text3); } else { result = CreateTableResult.Migrated; MigrateTable(mapping, tableInfo); } Dictionary<string, IndexInfo> dictionary = new Dictionary<string, IndexInfo>(); TableMapping.Column[] columns = mapping.Columns; foreach (TableMapping.Column column in columns) { foreach (IndexedAttribute index in column.Indices) { string text5 = index.Name ?? (mapping.TableName + "_" + column.Name); if (!dictionary.TryGetValue(text5, out var value)) { IndexInfo indexInfo = default(IndexInfo); indexInfo.IndexName = text5; indexInfo.TableName = mapping.TableName; indexInfo.Unique = index.Unique; indexInfo.Columns = new List<IndexedColumn>(); value = indexInfo; dictionary.Add(text5, value); } if (index.Unique != value.Unique) { throw new Exception("All the columns in an index must have the same value for their Unique property"); } value.Columns.Add(new IndexedColumn { Order = index.Order, ColumnName = column.Name }); } } foreach (string key in dictionary.Keys) { IndexInfo indexInfo2 = dictionary[key]; string[] columnNames = (from i in indexInfo2.Columns orderby i.Order select i.ColumnName).ToArray(); CreateIndex(key, indexInfo2.TableName, columnNames, indexInfo2.Unique); } return result; } public CreateTablesResult CreateTables<T, T2>(CreateFlags createFlags = CreateFlags.None) where T : new() where T2 : new() { return CreateTables(createFlags, typeof(T), typeof(T2)); } public CreateTablesResult CreateTables<T, T2, T3>(CreateFlags createFlags = CreateFlags.None) where T : new() where T2 : new() where T3 : new() { return CreateTables(createFlags, typeof(T), typeof(T2), typeof(T3)); } public CreateTablesResult CreateTables<T, T2, T3, T4>(CreateFlags createFlags = CreateFlags.None) where T : new() where T2 : new() where T3 : new() where T4 : new() { return CreateTables(createFlags, typeof(T), typeof(T2), typeof(T3), typeof(T4)); } public CreateTablesResult CreateTables<T, T2, T3, T4, T5>(CreateFlags createFlags = CreateFlags.None) where T : new() where T2 : new() where T3 : new() where T4 : new() where T5 : new() { return CreateTables(createFlags, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5)); } public CreateTablesResult CreateTables(CreateFlags createFlags = CreateFlags.None, params Type[] types) { CreateTablesResult createTablesResult = new CreateTablesResult(); foreach (Type type in types) { CreateTableResult value = CreateTable(type, createFlags); createTablesResult.Results[type] = value; } return createTablesResult; } public int CreateIndex(string indexName, string tableName, string[] columnNames, bool unique = false) { string query = string.Format("create {2} index if not exists \"{3}\" on \"{0}\"(\"{1}\")", tableName, string.Join("\", \"", columnNames), unique ? "unique" : "", indexName); return Execute(query); } public int CreateIndex(string indexName, string tableName, string columnName, bool unique = false) { return CreateIndex(indexName, tableName, new string[1] { columnName }, unique); } public int CreateIndex(string tableName, string columnName, bool unique = false) { return CreateIndex(tableName + "_" + columnName, tableName, columnName, unique); } public int CreateIndex(string tableName, string[] columnNames, bool unique = false) { return CreateIndex(tableName + "_" + string.Join("_", columnNames), tableName, columnNames, unique); } public int CreateIndex<T>(Expression<Func<T, object>> property, bool unique = false) { MemberExpression memberExpression = ((property.Body.NodeType != ExpressionType.Convert) ? (property.Body as MemberExpression) : (((UnaryExpression)property.Body).Operand as MemberExpression)); PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo; if (propertyInfo == null) { throw new ArgumentException("The lambda expression 'property' should point to a valid Property"); } string name = propertyInfo.Name; TableMapping mapping = GetMapping<T>(); string name2 = mapping.FindColumnWithPropertyName(name).Name; return CreateIndex(mapping.TableName, name2, unique); } public List<ColumnInfo> GetTableInfo(string tableName) { string query = "pragma table_info(\"" + tableName + "\")"; return Query<ColumnInfo>(query, Array.Empty<object>()); } private void MigrateTable(TableMapping map, List<ColumnInfo> existingCols) { List<TableMapping.Column> list = new List<TableMapping.Column>(); TableMapping.Column[] columns = map.Columns; foreach (TableMapping.Column column in columns) { bool flag = false; foreach (ColumnInfo existingCol in existingCols) { flag = string.Compare(column.Name, existingCol.Name, StringComparison.OrdinalIgnoreCase) == 0; if (flag) { break; } } if (!flag) { list.Add(column); } } foreach (TableMapping.Column item in list) { string query = "alter table \"" + map.TableName + "\" add column " + Orm.SqlDecl(item, StoreDateTimeAsTicks, StoreTimeSpanAsTicks); Execute(query); } } protected virtual SQLiteCommand NewCommand() { return new SQLiteCommand(this); } public SQLiteCommand CreateCommand(string cmdText, params object[] ps) { if (!_open) { throw SQLiteException.New(SQLite3.Result.Error, "Cannot create commands from unopened database"); } SQLiteCommand sQLiteCommand = NewCommand(); sQLiteCommand.CommandText = cmdText; foreach (object val in ps) { sQLiteCommand.Bind(val); } return sQLiteCommand; } public SQLiteCommand CreateCommand(string cmdText, Dictionary<string, object> args) { if (!_open) { throw SQLiteException.New(SQLite3.Result.Error, "Cannot create commands from unopened database"); } SQLiteCommand sQLiteCommand = NewCommand(); sQLiteCommand.CommandText = cmdText; foreach (KeyValuePair<string, object> arg in args) { sQLiteCommand.Bind(arg.Key, arg.Value); } return sQLiteCommand; } public int Execute(string query, params object[] args) { SQLiteCommand sQLiteCommand = CreateCommand(query, args); if (TimeExecution) { if (_sw == null) { _sw = new Stopwatch(); } _sw.Reset(); _sw.Start(); } int result = sQLiteCommand.ExecuteNonQuery(); if (TimeExecution) { _sw.Stop(); _elapsedMilliseconds += _sw.ElapsedMilliseconds; Tracer?.Invoke($"Finished in {_sw.ElapsedMilliseconds} ms ({(double)_elapsedMilliseconds / 1000.0:0.0} s total)"); } return result; } public T ExecuteScalar<T>(string query, params object[] args) { SQLiteCommand sQLiteCommand = CreateCommand(query, args); if (TimeExecution) { if (_sw == null) { _sw = new Stopwatch(); } _sw.Reset(); _sw.Start(); } T result = sQLiteCommand.ExecuteScalar<T>(); if (TimeExecution) { _sw.Stop(); _elapsedMilliseconds += _sw.ElapsedMilliseconds; Tracer?.Invoke($"Finished in {_sw.ElapsedMilliseconds} ms ({(double)_elapsedMilliseconds / 1000.0:0.0} s total)"); } return result; } public List<T> Query<T>(string query, params object[] args) where T : new() { SQLiteCommand sQLiteCommand = CreateCommand(query, args); return sQLiteCommand.ExecuteQuery<T>(); } public List<T> QueryScalars<T>(string query, params object[] args) { SQLiteCommand sQLiteCommand = CreateCommand(query, args); return sQLiteCommand.ExecuteQueryScalars<T>().ToList(); } public IEnumerable<T> DeferredQuery<T>(string query, params object[] args) where T : new() { SQLiteCommand sQLiteCommand = CreateCommand(query, args); return sQLiteCommand.ExecuteDeferredQuery<T>(); } public List<object> Query(TableMapping map, string query, params object[] args) { SQLiteCommand sQLiteCommand = CreateCommand(query, args); return sQLiteCommand.ExecuteQuery<object>(map); } public IEnumerable<object> DeferredQuery(TableMapping map, string query, params object[] args) { SQLiteCommand sQLiteCommand = CreateCommand(query, args); return sQLiteCommand.ExecuteDeferredQuery<object>(map); } public TableQuery<T> Table<T>() where T : new() { return new TableQuery<T>(this); } public T Get<T>(object pk) where T : new() { TableMapping mapping = GetMapping(typeof(T)); return Query<T>(mapping.GetByPrimaryKeySql, new object[1] { pk }).First(); } public object Get(object pk, TableMapping map) { return Query(map, map.GetByPrimaryKeySql, pk).First(); } public T Get<T>(Expression<Func<T, bool>> predicate) where T : new() { return Table<T>().Where(predicate).First(); } public T Find<T>(object pk) where T : new() { TableMapping mapping = GetMapping(typeof(T)); return Query<T>(mapping.GetByPrimaryKeySql, new object[1] { pk }).FirstOrDefault(); } public object Find(object pk, TableMapping map) { return Query(map, map.GetByPrimaryKeySql, pk).FirstOrDefault(); } public T Find<T>(Expression<Func<T, bool>> predicate) where T : new() { return Table<T>().Where(predicate).FirstOrDefault(); } public T FindWithQuery<T>(string query, params object[] args) where T : new() { return Query<T>(query, args).FirstOrDefault(); } public object FindWithQuery(TableMapping map, string query, params object[] args) { return Query(map, query, args).FirstOrDefault(); } public void BeginTransaction() { if (Interlocked.CompareExchange(ref _transactionDepth, 1, 0) == 0) { try { Execute("begin transaction"); return; } catch (Exception ex) { if (ex is SQLiteException ex2) { switch (ex2.Result) { case SQLite3.Result.Busy: case SQLite3.Result.NoMem: case SQLite3.Result.Interrupt: case SQLite3.Result.IOError: case SQLite3.Result.Full: RollbackTo(null, noThrow: true); break; } } else { Interlocked.Decrement(ref _transactionDepth); } throw; } } throw new InvalidOperationException("Cannot begin a transaction while already in a transaction."); } public string SaveTransactionPoint() { int num = Interlocked.Increment(ref _transactionDepth) - 1; string text = "S" + _rand.Next(32767) + "D" + num; try { Execute("savepoint " + text); } catch (Exception ex) { if (ex is SQLiteException ex2) { switch (ex2.Result) { case SQLite3.Result.Busy: case SQLite3.Result.NoMem: case SQLite3.Result.Interrupt: case SQLite3.Result.IOError: case SQLite3.Result.Full: RollbackTo(null, noThrow: true); break; } } else { Interlocked.Decrement(ref _transactionDepth); } throw; } return text; } public void Rollback() { RollbackTo(null, noThrow: false); } public void RollbackTo(string savepoint) { RollbackTo(savepoint, noThrow: false); } private void RollbackTo(string savepoint, bool noThrow) { try { if (string.IsNullOrEmpty(savepoint)) { if (Interlocked.Exchange(ref _transactionDepth, 0) > 0) { Execute("rollback"); } } else { DoSavePointExecute(savepoint, "rollback to "); } } catch (SQLiteException) { if (!noThrow) { throw; } } } public void Release(string savepoint) { try { DoSavePointExecute(savepoint, "release "); } catch (SQLiteException ex) { if (ex.Result == SQLite3.Result.Busy) { try { Execute("rollback"); } catch { } } throw; } } private void DoSavePointExecute(string savepoint, string cmd) { int num = savepoint.IndexOf('D'); if (num >= 2 && savepoint.Length > num + 1 && int.TryParse(savepoint.Substring(num + 1), out var result) && 0 <= result && result < _transactionDepth) { Thread.VolatileWrite(ref _transactionDepth, result); Execute(cmd + savepoint); return; } throw new ArgumentException("savePoint is not valid, and should be the result of a call to SaveTransactionPoint.", "savePoint"); } public void Commit() { if (Interlocked.Exchange(ref _transactionDepth, 0) == 0) { return; } try { Execute("commit"); } catch { try { Execute("rollback"); } catch { } throw; } } public void RunInTransaction(Action action) { try { string savepoint = SaveTransactionPoint(); action(); Release(savepoint); } catch (Exception) { Rollback(); throw; } } public int InsertAll(IEnumerable objects, bool runInTransaction = true) { int c = 0; if (runInTransaction) { RunInTransaction(delegate { foreach (object @object in objects) { c += Insert(@object); } }); } else { foreach (object object2 in objects) { c += Insert(object2); } } return c; } public int InsertAll(IEnumerable objects, string extra, bool runInTransaction = true) { int c = 0; if (runInTransaction) { RunInTransaction(delegate { foreach (object @object in objects) { c += Insert(@object, extra); } }); } else { foreach (object object2 in objects) { c += Insert(object2, extra); } } return c; } public int InsertAll(IEnumerable objects, Type objType, bool runInTransaction = true) { int c = 0; if (runInTransaction) { RunInTransaction(delegate { foreach (object @object in objects) { c += Insert(@object, objType); } }); } else { foreach (object object2 in objects) { c += Insert(object2, objType); } } return c; } public int Insert(object obj) { if (obj == null) { return 0; } return Insert(obj, "", Orm.GetType(obj)); } public int InsertOrReplace(object obj) { if (obj == null) { return 0; } return Insert(obj, "OR REPLACE", Orm.GetType(obj)); } public int Insert(object obj, Type objType) { return Insert(obj, "", objType); } public int InsertOrReplace(object obj, Type objType) { return Insert(obj, "OR REPLACE", objType); } public int Insert(object obj, string extra) { if (obj == null) { return 0; } return Insert(obj, extra, Orm.GetType(obj)); } public int Insert(object obj, string extra, Type objType) { if (obj == null || objType == null) { return 0; } TableMapping mapping = GetMapping(objType); if (mapping.PK != null && mapping.PK.IsAutoGuid && mapping.PK.GetValue(obj).Equals(Guid.Empty)) { mapping.PK.SetValue(obj, Guid.NewGuid()); } TableMapping.Column[] array = ((string.Compare(extra, "OR REPLACE", StringComparison.OrdinalIgnoreCase) == 0) ? mapping.InsertOrReplaceColumns : mapping.InsertColumns); object[] array2 = new object[array.Length]; for (int i = 0; i < array2.Length; i++) { array2[i] = array[i].GetValue(obj); } PreparedSqlLiteInsertCommand insertCommand = GetInsertCommand(mapping, extra); int num; lock (insertCommand) { try { num = insertCommand.ExecuteNonQuery(array2); } catch (SQLiteException ex) { if (SQLite3.ExtendedErrCode(Handle) == SQLite3.ExtendedResult.ConstraintNotNull) { throw NotNullConstraintViolationException.New(ex.Result, ex.Message, mapping, obj); } throw; } if (mapping.HasAutoIncPK) { long id = SQLite3.LastInsertRowid(Handle); mapping.SetAutoIncPK(obj, id); } } if (num > 0) { OnTableChanged(mapping, NotifyTableChangedAction.Insert); } return num; } private PreparedSqlLiteInsertCommand GetInsertCommand(TableMapping map, string extra) { Tuple<string, string> key = Tuple.Create(map.MappedType.FullName, extra); PreparedSqlLiteInsertCommand value; lock (_insertCommandMap) { if (_insertCommandMap.TryGetValue(key, out value)) { return value; } } value = CreateInsertCommand(map, extra); lock (_insertCommandMap) { if (_insertCommandMap.TryGetValue(key, out var value2)) { value.Dispose(); return value2; } _insertCommandMap.Add(key, value); } return value; } private PreparedSqlLiteInsertCommand CreateInsertCommand(TableMapping map, string extra) { TableMapping.Column[] array = map.InsertColumns; string commandText; if (array.Length == 0 && map.Columns.Length == 1 && map.Columns[0].IsAutoInc) { commandText = string.Format("insert {1} into \"{0}\" default values", map.TableName, extra); } else { if (string.Compare(extra, "OR REPLACE", StringComparison.OrdinalIgnoreCase) == 0) { array = map.InsertOrReplaceColumns; } commandText = string.Format("insert {3} into \"{0}\"({1}) values ({2})", map.TableName, string.Join(",", array.Select((TableMapping.Column c) => "\"" + c.Name + "\"").ToArray()), string.Join(",", array.Select((TableMapping.Column c) => "?").ToArray()), extra); } return new PreparedSqlLiteInsertCommand(this, commandText); } public int Update(object obj) { if (obj == null) { return 0; } return Update(obj, Orm.GetType(obj)); } public int Update(object obj, Type objType) { int num = 0; if (obj == null || objType == null) { return 0; } TableMapping mapping = GetMapping(objType); TableMapping.Column pk = mapping.PK; if (pk == null) { throw new NotSupportedException("Cannot update " + mapping.TableName + ": it has no PK"); } IEnumerable<TableMapping.Column> source = mapping.Columns.Where((TableMapping.Column p) => p != pk); IEnumerable<object> collection = source.Select((TableMapping.Column c) => c.GetValue(obj)); List<object> list = new List<object>(collection); if (list.Count == 0) { source = mapping.Columns; collection = source.Select((TableMapping.Column c) => c.GetValue(obj)); list = new List<object>(collection); } list.Add(pk.GetValue(obj)); string query = string.Format("update \"{0}\" set {1} where \"{2}\" = ? ", mapping.TableName, string.Join(",", source.Select((TableMapping.Column c) => "\"" + c.Name + "\" = ? ").ToArray()), pk.Name); try { num = Execute(query, list.ToArray()); } catch (SQLiteException ex) { if (ex.Result == SQLite3.Result.Constraint && SQLite3.ExtendedErrCode(Handle) == SQLite3.ExtendedResult.ConstraintNotNull) { throw NotNullConstraintViolationException.New(ex, mapping, obj); } throw; } if (num > 0) { OnTableChanged(mapping, NotifyTableChangedAction.Update); } return num; } public int UpdateAll(IEnumerable objects, bool runInTransaction = true) { int c = 0; if (runInTransaction) { RunInTransaction(delegate { foreach (object @object in objects) { c += Update(@object); } }); } else { foreach (object object2 in objects) { c += Update(object2); } } return c; } public int Delete(object objectToDelete) { TableMapping mapping = GetMapping(Orm.GetType(objectToDelete)); TableMapping.Column pK = mapping.PK; if (pK == null) { throw new NotSupportedException("Cannot delete " + mapping.TableName + ": it has no PK"); } string query = $"delete from \"{mapping.TableName}\" where \"{pK.Name}\" = ?"; int num = Execute(query, pK.GetValue(objectToDelete)); if (num > 0) { OnTableChanged(mapping, NotifyTableChangedAction.Delete); } return num; } public int Delete<T>(object primaryKey) { return Delete(primaryKey, GetMapping(typeof(T))); } public int Delete(object primaryKey, TableMapping map) { TableMapping.Column pK = map.PK; if (pK == null) { throw new NotSupportedException("Cannot delete " + map.TableName + ": it has no PK"); } string query = $"delete from \"{map.TableName}\" where \"{pK.Name}\" = ?"; int num = Execute(query, primaryKey); if (num > 0) { OnTableChanged(map, NotifyTableChangedAction.Delete); } return num; } public int DeleteAll<T>() { TableMapping mapping = GetMapping(typeof(T)); return DeleteAll(mapping); } public int DeleteAll(TableMapping map) { string query = $"delete from \"{map.TableName}\""; int num = Execute(query); if (num > 0) { OnTableChanged(map, NotifyTableChangedAction.Delete); } return num; } public void Backup(string destinationDatabasePath, string databaseName = "main") { SQLite3.Result result = SQLite3.Open(destinationDatabasePath, out var db); if (result != 0) { throw SQLiteException.New(result, "Failed to open destination database"); } IntPtr intPtr = SQLite3.BackupInit(db, databaseName, Handle, databaseName); if (intPtr == NullBackupHandle) { SQLite3.Close(db); throw new Exception("Failed to create backup"); } SQLite3.BackupStep(intPtr, -1); SQLite3.BackupFinish(intPtr); result = SQLite3.GetResult(db); string message = ""; if (result != 0) { message = SQLite3.GetErrmsg(db); } SQLite3.Close(db); if (result != 0) { throw SQLiteException.New(result, message); } } ~SQLiteConnection() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } public void Close() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { bool flag = LibVersionNumber >= 3007014; if (!_open || !(Handle != NullHandle)) { return; } try { if (disposing) { lock (_insertCommandMap) { foreach (PreparedSqlLiteInsertCommand value in _insertCommandMap.Values) { value.Dispose(); } _insertCommandMap.Clear(); } SQLite3.Result result = (flag ? SQLite3.Close2(Handle) : SQLite3.Close(Handle)); if (result != 0) { string errmsg = SQLite3.GetErrmsg(Handle); throw SQLiteException.New(result, errmsg); } } else { SQLite3.Result result2 = (flag ? SQLite3.Close2(Handle) : SQLite3.Close(Handle)); } } finally { Handle = NullHandle; _open = false; } } private void OnTableChanged(TableMapping table, NotifyTableChangedAction action) { this.TableChanged?.Invoke(this, new NotifyTableChangedEventArgs(table, action)); } } public class NotifyTableChangedEventArgs : EventArgs { public TableMapping Table { get; private set; } public NotifyTableChangedAction Action { get; private set; } public NotifyTableChangedEventArgs(TableMapping table, NotifyTableChangedAction action) { Table = table; Action = action; } } public enum NotifyTableChangedAction { Insert, Update, Delete } public class SQLiteConnectionString { private const string DateTimeSqliteDefaultFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff"; public string UniqueKey { get; } public string DatabasePath { get; } public bool StoreDateTimeAsTicks { get; } public bool StoreTimeSpanAsTicks { get; } public string DateTimeStringFormat { get; } public DateTimeStyles DateTimeStyle { get; } public object Key { get; } public SQLiteOpenFlags OpenFlags { get; } public Action<SQLiteConnection> PreKeyAction { get; } public Action<SQLiteConnection> PostKeyAction { get; } public string VfsName { get; } public SQLiteConnectionString(string databasePath, bool storeDateTimeAsTicks = true) : this(databasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create, storeDateTimeAsTicks) { } public SQLiteConnectionString(string databasePath, bool storeDateTimeAsTicks, object key = null, Action<SQLiteConnection> preKeyAction = null, Action<SQLiteConnection> postKeyAction = null, string vfsName = null) : this(databasePath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create, storeDateTimeAsTicks, key, preKeyAction, postKeyAction, vfsName) { } public SQLiteConnectionString(string databasePath, SQLiteOpenFlags openFlags, bool storeDateTimeAsTicks, object key = null, Action<SQLiteConnection> preKeyAction = null, Action<SQLiteConnection> postKeyAction = null, string vfsName = null, string dateTimeStringFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff", bool storeTimeSpanAsTicks = true) { if (key != null && !(key is byte[]) && !(key is string)) { throw new ArgumentException("Encryption keys must be strings or byte arrays", "key"); } UniqueKey = $"{databasePath}_{(uint)openFlags:X8}"; StoreDateTimeAsTicks = storeDateTimeAsTicks; StoreTimeSpanAsTicks = storeTimeSpanAsTicks; DateTimeStringFormat = dateTimeStringFormat; DateTimeStyle = (("o".Equals(DateTimeStringFormat, StringComparison.OrdinalIgnoreCase) || "r".Equals(DateTimeStringFormat, StringComparison.OrdinalIgnoreCase)) ? DateTimeStyles.RoundtripKind : DateTimeStyles.None); Key = key; PreKeyAction = preKeyAction; PostKeyAction = postKeyAction; OpenFlags = openFlags; VfsName = vfsName; DatabasePath = databasePath; } } [AttributeUsage(AttributeTargets.Class)] public class TableAttribute : Attribute { public string Name { get; set; } public bool WithoutRowId { get; set; } public TableAttribute(string name) { Name = name; } } [AttributeUsage(AttributeTargets.Property)] public class ColumnAttribute : Attribute { public string Name { get; set; } public ColumnAttribute(string name) { Name = name; } } [AttributeUsage(AttributeTargets.Property)] public class PrimaryKeyAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property)] public class AutoIncrementAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] public class IndexedAttribute : Attribute { public string Name { get; set; } public int Order { get; set; } public virtual bool Unique { get; set; } public IndexedAttribute() { } public IndexedAttribute(string name, int order) { Name = name; Order = order; } } [AttributeUsage(AttributeTargets.Property)] public class IgnoreAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property)] public class UniqueAttribute : IndexedAttribute { public override bool Unique { get { return true; } set { } } } [AttributeUsage(AttributeTargets.Property)] public class MaxLengthAttribute : Attribute { public int Value { get; private set; } public MaxLengthAttribute(int length) { Value = length; } } public sealed class PreserveAttribute : Attribute { public bool AllMembers; public bool Conditional; } [AttributeUsage(AttributeTargets.Property)] public class CollationAttribute : Attribute { public string Value { get; private set; } public CollationAttribute(string collation) { Value = collation; } } [AttributeUsage(AttributeTargets.Property)] public class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Enum)] public class StoreAsTextAttribute : Attribute { } public class TableMapping { public class Column { private MemberInfo _member; public string Name { get; private set; } public PropertyInfo PropertyInfo => _member as PropertyInfo; public string PropertyName => _member.Name; public Type ColumnType { get; private set; } public string Collation { get; private set; } public bool IsAutoInc { get; private set; } public bool IsAutoGuid { get; private set; } public bool IsPK { get; private set; } public IEnumerable<IndexedAttribute> Indices { get; set; } public bool IsNullable { get; private set; } public int? MaxStringLength { get; private set; } public bool StoreAsText { get; private set; } public Column(MemberInfo member, CreateFlags createFlags = CreateFlags.None) { _member = member; Type memberType = GetMemberType(member); CustomAttributeData customAttributeData = member.CustomAttributes.FirstOrDefault((CustomAttributeData x) => x.AttributeType == typeof(ColumnAttribute)); Name = ((customAttributeData == null || customAttributeData.ConstructorArguments.Count <= 0) ? member.Name : customAttributeData.ConstructorArguments[0].Value?.ToString()); ColumnType = Nullable.GetUnderlyingType(memberType) ?? memberType; Collation = Orm.Collation(member); IsPK = Orm.IsPK(member) || ((createFlags & CreateFlags.ImplicitPK) == CreateFlags.ImplicitPK && string.Compare(member.Name, "Id", StringComparison.OrdinalIgnoreCase) == 0); bool flag = Orm.IsAutoInc(member) || (IsPK && (createFlags & CreateFlags.AutoIncPK) == CreateFlags.AutoIncPK); IsAutoGuid = flag && ColumnType == typeof(Guid); IsAutoInc = flag && !IsAutoGuid; Indices = Orm.GetIndices(member); if (!Indices.Any() && !IsPK && (createFlags & CreateFlags.ImplicitIndex) == CreateFlags.ImplicitIndex && Name.EndsWith("Id", StringComparison.OrdinalIgnoreCase)) { Indices = new IndexedAttribute[1] { new IndexedAttribute() }; } IsNullable = !IsPK && !Orm.IsMarkedNotNull(member); MaxStringLength = Orm.MaxStringLength(member); StoreAsText = memberType.GetTypeInfo().CustomAttributes.Any((CustomAttributeData x) => x.AttributeType == typeof(StoreAsTextAttribute)); } public Column(PropertyInfo member, CreateFlags createFlags = CreateFlags.None) : this((MemberInfo)member, createFlags) { } public void SetValue(object obj, object val) { if (_member is PropertyInfo propertyInfo) { if (val != null && ColumnType.GetTypeInfo().IsEnum) { propertyInfo.SetValue(obj, Enum.ToObject(ColumnType, val)); } else { propertyInfo.SetValue(obj, val); } return; } if (_member is FieldInfo fieldInfo) { if (val != null && ColumnType.GetTypeInfo().IsEnum) { fieldInfo.SetValue(obj, Enum.ToObject(ColumnType, val)); } else { fieldInfo.SetValue(obj, val); } return; } throw new InvalidProgramException("unreachable condition"); } public object GetValue(object obj) { if (_member is PropertyInfo propertyInfo) { return propertyInfo.GetValue(obj); } if (_member is FieldInfo fieldInfo) { return fieldInfo.GetValue(obj); } throw new InvalidProgramException("unreachable condition"); } private static Type GetMemberType(MemberInfo m) { return m.MemberType switch { MemberTypes.Property => ((PropertyInfo)m).PropertyType, MemberTypes.Field => ((FieldInfo)m).FieldType, _ => throw new InvalidProgramException("TableMapping supports properties or fields only."), }; } } internal enum MapMethod { ByName, ByPosition } private readonly Column _autoPk; private readonly Column[] _insertColumns; private readonly Column[] _insertOrReplaceColumns; public Type MappedType { get; private set; } public string TableName { get; private set; } public bool WithoutRowId { get; private set; } public Column[] Columns { get; private set; } public Column PK { get; private set; } public string GetByPrimaryKeySql { get; private set; } public CreateFlags CreateFlags { get; private set; } internal MapMethod Method { get; private set; } = MapMethod.ByName; public bool HasAutoIncPK { get; private set; } public Column[] InsertColumns => _insertColumns; public Column[] InsertOrReplaceColumns => _insertOrReplaceColumns; public TableMapping(Type type, CreateFlags createFlags = CreateFlags.None) { MappedType = type; CreateFlags = createFlags; TypeInfo typeInfo = type.GetTypeInfo(); TableAttribute tableAttribute = (from x in typeInfo.CustomAttributes where x.AttributeType == typeof(TableAttribute) select (TableAttribute)Orm.InflateAttribute(x)).FirstOrDefault(); TableName = ((tableAttribute != null && !string.IsNullOrEmpty(tableAttribute.Name)) ? tableAttribute.Name : MappedType.Name); WithoutRowId = tableAttribute?.WithoutRowId ?? false; IReadOnlyCollection<MemberInfo> publicMembers = GetPublicMembers(type); List<Column> list = new List<Column>(publicMembers.Count); foreach (MemberInfo item in publicMembers) { if (!item.IsDefined(typeof(IgnoreAttribute), inherit: true)) { list.Add(new Column(item, createFlags)); } } Columns = list.ToArray(); Column[] columns = Columns; foreach (Column column in columns) { if (column.IsAutoInc && column.IsPK) { _autoPk = column; } if (column.IsPK) { PK = column; } } HasAutoIncPK = _autoPk != null; if (PK != null) { GetByPrimaryKeySql = $"select * from \"{TableName}\" where \"{PK.Name}\" = ?"; } else { GetByPrimaryKeySql = $"select * from \"{TableName}\" limit 1"; } _insertColumns = Columns.Where((Column c) => !c.IsAutoInc).ToArray(); _insertOrReplaceColumns = Columns.ToArray(); } private IReadOnlyCollection<MemberInfo> GetPublicMembers(Type type) { if (type.Name.StartsWith("ValueTuple`")) { return GetFieldsFromValueTuple(type); } List<MemberInfo> list = new List<MemberInfo>(); HashSet<string> memberNames = new HashSet<string>(); List<MemberInfo> list2 = new List<MemberInfo>(); do { TypeInfo typeInfo = type.GetTypeInfo(); list2.Clear(); list2.AddRange(typeInfo.DeclaredProperties.Where((PropertyInfo p) => !memberNames.Contains(p.Name) && p.CanRead && p.CanWrite && p.GetMethod != null && p.SetMethod != null && p.GetMethod.IsPublic && p.SetMethod.IsPublic && !p.GetMethod.IsStatic && !p.SetMethod.IsStatic)); list.AddRange(list2); foreach (MemberInfo item in list2) { memberNames.Add(item.Name); } type = typeInfo.BaseType; } while (type != typeof(object)); return list; } private IReadOnlyCollection<MemberInfo> GetFieldsFromValueTuple(Type type) { Method = MapMethod.ByPosition; FieldInfo[] fields = type.GetFields(); if (fields.Length >= 8) { throw new NotSupportedException("ValueTuple with more than 7 members not supported due to nesting; see https://docs.microsoft.com/en-us/dotnet/api/system.valuetuple-8.rest"); } return (IReadOnlyCollection<MemberInfo>)(object)fields; } public void SetAutoIncPK(object obj, long id) { if (_autoPk != null) { _autoPk.SetValue(obj, Convert.ChangeType(id, _autoPk.ColumnType, null)); } } public Column FindColumnWithPropertyName(string propertyName) { return Columns.FirstOrDefault((Column c) => c.PropertyName == propertyName); } public Column FindColumn(string columnName) { if (Method != 0) { throw new InvalidOperationException(string.Format("This {0} is not mapped by name, but {1}.", "TableMapping", Method)); } return Columns.FirstOrDefault((Column c) => c.Name.ToLower() == columnName.ToLower()); } } internal class EnumCacheInfo { public bool IsEnum { get; private set; } public bool StoreAsText { get; private set; } public Dictionary<int, string> EnumValues { get; private set; } public EnumCacheInfo(Type type) { TypeInfo typeInfo = type.GetTypeInfo(); IsEnum = typeInfo.IsEnum; if (!IsEnum) { return; } StoreAsText = typeInfo.CustomAttributes.Any((CustomAttributeData x) => x.AttributeType == typeof(StoreAsTextAttribute)); if (!StoreAsText) { return; } EnumValues = new Dictionary<int, string>(); foreach (object value in Enum.GetValues(type)) { EnumValues[Convert.ToInt32(value)] = value.ToString(); } } } internal static class EnumCache { private static readonly Dictionary<Type, EnumCacheInfo> Cache = new Dictionary<Type, EnumCacheInfo>(); public static EnumCacheInfo GetInfo<T>() { return GetInfo(typeof(T)); } public static EnumCacheInfo GetInfo(Type type) { lock (Cache) { EnumCacheInfo value = null; if (!Cache.TryGetValue(type, out value)) { value = new EnumCacheInfo(type); Cache[type] = value; } return value; } } } public static class Orm { public const int DefaultMaxStringLength = 140; public const string ImplicitPkName = "Id"; public const string ImplicitIndexSuffix = "Id"; public static Type GetType(object obj) { if (obj == null) { return typeof(object); } if (obj is IReflectableType reflectableType) { return reflectableType.GetTypeInfo().AsType(); } return obj.GetType(); } public static string SqlDecl(TableMapping.Column p, bool storeDateTimeAsTicks, bool storeTimeSpanAsTicks) { string text = "\"" + p.Name + "\" " + SqlType(p, storeDateTimeAsTicks, storeTimeSpanAsTicks) + " "; if (p.IsPK) { text += "primary key "; } if (p.IsAutoInc) { text += "autoincrement "; } if (!p.IsNullable) { text += "not null "; } if (!string.IsNullOrEmpty(p.Collation)) { text = text + "collate " + p.Collation + " "; } return text; } public static string SqlType(TableMapping.Column p, bool storeDateTimeAsTicks, bool storeTimeSpanAsTicks) { Type columnType = p.ColumnType; if (columnType == typeof(bool) || columnType == typeof(byte) || columnType == typeof(ushort) || columnType == typeof(sbyte) || columnType == typeof(short) || columnType == typeof(int) || columnType == typeof(uint) || columnType == typeof(long) || columnType == typeof(ulong)) { return "integer"; } if (columnType == typeof(float) || columnType == typeof(double) || columnType == typeof(decimal)) { return "float"; } if (columnType == typeof(string) || columnType == typeof(StringBuilder) || columnType == typeof(Uri) || columnType == typeof(UriBuilder)) { int? maxStringLength = p.MaxStringLength; if (maxStringLength.HasValue) { return "varchar(" + maxStringLength.Value + ")"; } return "varchar"; } if (columnType == typeof(TimeSpan)) { return storeTimeSpanAsTicks ? "bigint" : "time"; } if (columnType == typeof(DateTime)) { return storeDateTimeAsTicks ? "bigint" : "datetime"; } if (columnType == typeof(DateTimeOffset)) { return "bigint"; } if (columnType.GetTypeInfo().IsEnum) { if (p.StoreAsText) { return "varchar"; } return "integer"; } if (columnType == typeof(byte[])) { return "blob"; } if (columnType == typeof(Guid)) { return "varchar(36)"; } throw new NotSupportedException("Don't know about " + columnType); } public static bool IsPK(MemberInfo p) { return p.CustomAttributes.Any((CustomAttributeData x) => x.AttributeType == typeof(PrimaryKeyAttribute)); } public static string Collation(MemberInfo p) { return p.CustomAttributes.Where((CustomAttributeData x) => typeof(CollationAttribute) == x.AttributeType).Select(delegate(CustomAttributeData x) { IList<CustomAttributeTypedArgument> constructorArguments = x.ConstructorArguments; return (constructorArguments.Count > 0) ? ((constructorArguments[0].Value as string) ?? "") : ""; }).FirstOrDefault() ?? ""; } public static bool IsAutoInc(MemberInfo p) { return p.CustomAttributes.Any((CustomAttributeData x) => x.AttributeType == typeof(AutoIncrementAttribute)); } public static FieldInfo GetField(TypeInfo t, string name) { FieldInfo declaredField = t.GetDeclaredField(name); if (declaredField != null) { return declaredField; } return GetField(t.BaseType.GetTypeInfo(), name); } public static PropertyInfo GetProperty(TypeInfo t, string name) { PropertyInfo declaredProperty = t.GetDeclaredProperty(name); if (declaredProperty != null) { return declaredProperty; } return GetProperty(t.BaseType.GetTypeInfo(), name); } public static object InflateAttribute(CustomAttributeData x) { Type attributeType = x.AttributeType; TypeInfo typeInfo = attributeType.GetTypeInfo(); object[] args = x.ConstructorArguments.Select((CustomAttributeTypedArgument a) => a.Value).ToArray(); object obj = Activator.CreateInstance(x.AttributeType, args); foreach (CustomAttributeNamedArgument namedArgument in x.NamedArguments) { if (namedArgument.IsField) { GetField(typeInfo, namedArgument.MemberName).SetValue(obj, namedArgument.TypedValue.Value); } else { GetProperty(typeInfo, namedArgument.MemberName).SetValue(obj, namedArgument.TypedValue.Value); } } return obj; } public static IEnumerable<IndexedAttribute> GetIndices(MemberInfo p) { TypeInfo indexedInfo = typeof(IndexedAttribute).GetTypeInfo(); return from x in p.CustomAttributes where indexedInfo.IsAssignableFrom(x.AttributeType.GetTypeInfo()) select (IndexedAttribute)InflateAttribute(x); } public static int? MaxStringLength(MemberInfo p) { CustomAttributeData customAttributeData = p.CustomAttributes.FirstOrDefault((CustomAttributeData x) => x.AttributeType == typeof(MaxLengthAttribute)); if (customAttributeData != null) { MaxLengthAttribute maxLengthAttribute = (MaxLengthAttribute)InflateAttribute(customAttributeData); return maxLengthAttribute.Value; } return null; } public static int? MaxStringLength(PropertyInfo p) { return MaxStringLength((MemberInfo)p); } public static bool IsMarkedNotNull(MemberInfo p) { return p.CustomAttributes.Any((CustomAttributeData x) => x.AttributeType == typeof(NotNullAttribute)); } } public class SQLiteCommand { private class Binding { public string Name { get; set; } public object Value { get; set; } public int Index { get; set; } } [CompilerGenerated] private sealed class <ExecuteDeferredQuery>d__12<T> : IEnumerable<T>, IEnumerable, IEnumerator<T>, IDisposable, IEnumerator { private int <>1__state; private T <>2__current; private int <>l__initialThreadId; private TableMapping map; public TableMapping <>3__map; public SQLiteCommand <>4__this; private IntPtr <stmt>5__1; private TableMapping.Column[] <cols>5__2; private Action<object, IntPtr, int>[] <fastColumnSetters>5__3; private MethodInfo <getSetter>5__4; private int <i>5__5; private string <name>5__6; private object <obj>5__7; private int <i>5__8; private SQLite3.ColType <colType>5__9; private object <val>5__10; T IEnumerator<T>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExecuteDeferredQuery>d__12(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <cols>5__2 = null; <fastColumnSetters>5__3 = null; <getSetter>5__4 = null; <name>5__6 = null; <obj>5__7 = null; <val>5__10 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this._conn.Trace) { <>4__this._conn.Tracer?.Invoke("Executing Query: " + <>4__this); } <stmt>5__1 = <>4__this.Prepare(); <>1__state = -3; <cols>5__2 = new TableMapping.Column[SQLite3.ColumnCount(<stmt>5__1)]; <fastColumnSetters>5__3 = new Action<object, IntPtr, int>[SQLite3.ColumnCount(<stmt>5__1)]; if (map.Method == TableMapping.MapMethod.ByPosition) { Array.Copy(map.Columns, <cols>5__2, Math.Min(<cols>5__2.Length, map.Columns.Length)); } else { if (map.Method != 0) { break; } <getSetter>5__4 = null; if (typeof(T) != map.MappedType) { <getSetter>5__4 = FastColumnSetter.GetFastSetterMethodInfoUnsafe(map.MappedType); } <i>5__5 = 0; while (<i>5__5 < <cols>5__2.Length) { <name>5__6 = SQLite3.ColumnName16(<stmt>5__1, <i>5__5); <cols>5__2[<i>5__5] = map.FindColumn(<name>5__6); if (<cols>5__2[<i>5__5] != null) { if (<getSetter>5__4 != null) { <fastColumnSetters>5__3[<i>5__5] = (Action<object, IntPtr, int>)<getSetter>5__4.Invoke(null, new object[2] { <>4__this._conn, <cols>5__2[<i>5__5] }); } else { <fastColumnSetters>5__3[<i>5__5] = FastColumnSetter.GetFastSetter<T>(<>4__this._conn, <cols>5__2[<i>5__5]); } } <name>5__6 = null; <i>5__5++; } <getSetter>5__4 = null; } break; case 1: <>1__state = -3; <obj>5__7 = null; break; } if (SQLite3.Step(<stmt>5__1) == SQLite3.Result.Row) { <obj>5__7 = Activator.CreateInstance(map.MappedType); <i>5__8 = 0; while (<i>5__8 < <cols>5__2.Length) { if (<cols>5__2[<i>5__8] != null) { if (<fastColumnSetters>5__3[<i>5__8] != null) { <fastColumnSetters>5__3[<i>5__8](<obj>5__7, <stmt>5__1, <i>5__8); } else { <colType>5__9 = SQLite3.ColumnType(<stmt>5__1, <i>5__8); <val>5__10 = <>4__this.ReadCol(<stmt>5__1, <i>5__8, <colType>5__9, <cols>5__2[<i>5__8].ColumnType); <cols>5__2[<i>5__8].SetValue(<obj>5__7, <val>5__10); <val>5__10 = null; } } <i>5__8++; } <>4__this.OnInstanceCreated(<obj>5__7); <>2__current = (T)<obj>5__7; <>1__state = 1; return true; } <cols>5__2 = null; <fastColumnSetters>5__3 = null; <>m__Finally1(); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; SQLite3.Finalize(<stmt>5__1); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<T> IEnumerable<T>.GetEnumerator() { <ExecuteDeferredQuery>d__12<T> <ExecuteDeferredQuery>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <ExecuteDeferredQuery>d__ = this; } else { <ExecuteDeferredQuery>d__ = new <ExecuteDeferredQuery>d__12<T>(0) { <>4__this = <>4__this }; } <ExecuteDeferredQuery>d__.map = <>3__map; return <ExecuteDeferredQuery>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<T>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <ExecuteQueryScalars>d__14<T> : IEnumerable<T>, IEnumerable, IEnumerator<T>, IDisposable, IEnumerator { private int <>1__state; private T <>2__current; private int <>l__initialThreadId; public SQLiteCommand <>4__this; private IntPtr <stmt>5__1; private SQLite3.ColType <colType>5__2; private object <val>5__3; T IEnumerator<T>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExecuteQueryScalars>d__14(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <val>5__3 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (<>4__this._conn.Trace) { <>4__this._conn.Tracer?.Invoke("Executing Query: " + <>4__this); } <stmt>5__1 = <>4__this.Prepare(); <>1__state = -3; if (SQLite3.ColumnCount(<stmt>5__1) < 1) { throw new InvalidOperationException("QueryScalars should return at least one column"); } break; case 1: <>1__state = -3; goto IL_0154; case 2: { <>1__state = -3; goto IL_0154; } IL_0154: <val>5__3 = null; break; } if (SQLite3.Step(<stmt>5__1) == SQLite3.Result.Row) { <colType>5__2 = SQLite3.ColumnType(<stmt>5__1, 0); <val>5__3 = <>4__this.ReadCol(<stmt>5__1, 0, <colType>5__2, typeof(T)); if (<val>5__3 == null) { <>2__current = default(T); <>1__state = 1; return true; } <>2__current = (T)<val>5__3; <>1__state = 2; return true; } <>m__Finally1(); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; <>4__this.Finalize(<stmt>5__1); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<T> IEnumerable<T>.GetEnumerator() { <ExecuteQueryScalars>d__14<T> result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <ExecuteQueryScalars>d__14<T>(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<T>)this).GetEnumerator(); } } private SQLiteConnection _conn; private List<Binding> _bindings; private static IntPtr NegativePointer = new IntPtr(-1); public string CommandText { get; set; } public SQLiteCommand(SQLiteConnection conn) { _conn = conn; _bindings = new List<Binding>(); CommandText = ""; } public int ExecuteNonQuery() { if (_conn.Trace) { _conn.Tracer?.Invoke("Executing: " + this); } SQLite3.Result result = SQLite3.Result.OK; IntPtr stmt = Prepare(); result = SQLite3.Step(stmt); Finalize(stmt); switch (result) { case SQLite3.Result.Done: return SQLite3.Changes(_conn.Handle); case SQLite3.Result.Error: { string errmsg = SQLite3.GetErrmsg(_conn.Handle); throw SQLiteException.New(result, errmsg); } case SQLite3.Result.Constraint: if (SQLite3.ExtendedErrCode(_conn.Handle) == SQLite3.ExtendedResult.ConstraintNotNull) { throw NotNullConstraintViolationException.New(result, SQLite3.GetErrmsg(_conn.Handle)); } break; } throw SQLiteException.New(result, SQLite3.GetErrmsg(_conn.Handle)); } public IEnumerable<T> ExecuteDeferredQuery<T>() { return ExecuteDeferredQuery<T>(_conn.GetMapping(typeof(T))); } public List<T> ExecuteQuery<T>() { return ExecuteDeferredQuery<T>(_conn.GetMapping(typeof(T))).ToList(); } public List<T> ExecuteQuery<T>(TableMapping map) { return ExecuteDeferredQuery<T>(map).ToList(); } protected virtual void OnInstanceCreated(object obj) { } [IteratorStateMachine(typeof(<ExecuteDeferredQuery>d__12<>))] public IEnumerable<T> ExecuteDeferredQuery<T>(TableMapping map) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExecuteDeferredQuery>d__12<T>(-2) { <>4__this = this, <>3__map = map }; } public T ExecuteScalar<T>() { if (_conn.Trace) { _conn.Tracer?.Invoke("Executing Query: " + this); } T result = default(T); IntPtr stmt = Prepare(); try { SQLite3.Result result2 = SQLite3.Step(stmt); switch (result2) { case SQLite3.Result.Row: { SQLite3.ColType type = SQLite3.ColumnType(stmt, 0); object obj = ReadCol(stmt, 0, type, typeof(T)); if (obj != null) { result = (T)obj; return result; } break; } case SQLite3.Result.Done: break; default: throw SQLiteException.New(result2, SQLite3.GetErrmsg(_conn.Handle)); } } finally { Finalize(stmt); } return result; } [IteratorStateMachine(typeof(<ExecuteQueryScalars>d__14<>))] public IEnumerable<T> ExecuteQueryScalars<T>() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExecuteQueryScalars>d__14<T>(-2) { <>4__this = this }; } public void Bind(string name, object val) { _bindings.Add(new Binding { Name = name, Value = val }); } public void Bind(object val) { Bind(null, val); } public override string ToString() { string[] array = new string[1 + _bindings.Count]; array[0] = CommandText; int num = 1; foreach (Binding binding in _bindings) { array[num] = $" {num - 1}: {binding.Value}"; num++; } return string.Join(Environment.NewLine, array); } private IntPtr Prepare() { IntPtr intPtr = SQLite3.Prepare2(_conn.Handle, CommandText); BindAll(intPtr); return intPtr; } private void Finalize(IntPtr stmt) { SQLite3.Finalize(stmt); } private void BindAll(IntPtr stmt) { int num = 1; foreach (Binding binding in _bindings) { if (binding.Name != null) { binding.Index = SQLite3.BindParameterIndex(stmt, binding.Name); } else { binding.Index = num++; } BindParameter(stmt, binding.Index, binding.Value, _conn.StoreDateTimeAsTicks, _conn.DateTimeStringFormat, _conn.StoreTimeSpanAsTicks); } } internal static void BindParameter(IntPtr stmt, int index, object value, bool storeDateTimeAsTicks, string dateTimeStringFormat, bool storeTimeSpanAsTicks) { if (value == null) { SQLite3.BindNull(stmt, index); return; } if (value is int) { SQLite3.BindInt(stmt, index, (int)value); return; } if (value is string) { SQLite3.BindText(stmt, index, (string)value, -1, NegativePointer); return; } if (value is byte || value is ushort || value is sbyte || value is short) { SQLite3.BindInt(stmt, index, Convert.ToInt32(value)); return; } if (value is bool) { SQLite3.BindInt(stmt, index, ((bool)value) ? 1 : 0); return; } if (value is uint || value is long || value is ulong) { SQLite3.BindInt64(stmt, index, Convert.ToInt64(value)); return; } if (value is float || value is double || value is decimal) { SQLite3.BindDouble(stmt, index, Convert.ToDouble(value)); return; } if (value is TimeSpan) { if (storeTimeSpanAsTicks) { SQLite3.BindInt64(stmt, index, ((TimeSpan)value).Ticks); } else { SQLite3.BindText(stmt, index, ((TimeSpan)value).ToString(), -1, NegativePointer); } return; } if (value is DateTime) { if (storeDateTimeAsTicks) { SQLite3.BindInt64(stmt, index, ((DateTime)value).Ticks); } else { SQLite3.BindText(stmt, index, ((DateTime)value).ToString(dateTimeStringFormat, CultureInfo.InvariantCulture), -1, NegativePointer); } return; } if (value is DateTimeOffset) { SQLite3.BindInt64(stmt, index, ((DateTimeOffset)value).UtcTicks); return; } if (value is byte[]) { SQLite3.BindBlob(stmt, index, (byte[])value, ((byte[])value).Length, NegativePointer); return; } if (value is Guid) { SQLite3.BindText(stmt, index, ((Guid)value).ToString(), 72, NegativePointer); return; } if (value is Uri) { SQLite3.BindText(stmt, index, ((Uri)value).ToString(), -1, NegativePointer); return; } if (value is StringBuilder) { SQLite3.BindText(stmt, index, ((StringBuilder)value).ToString(), -1, NegativePointer); return; } if (value is UriBuilder) { SQLite3.BindText(stmt, index, ((UriBuilder)value).ToString(), -1, NegativePointer); return; } Type type = value.GetType(); EnumCacheInfo info = EnumCache.GetInfo(type); if (info.IsEnum) { int num = Convert.ToInt32(value); if (info.StoreAsText) { SQLite3.BindText(stmt, index, info.EnumValues[num], -1, NegativePointer); } else { SQLite3.BindInt(stmt, index, num); } return; } throw new NotSupportedException("Cannot store type: " + Orm.GetType(value)); } private object ReadCol(IntPtr stmt, int index, SQLite3.ColType type, Type clrType) { if (type == SQLite3.ColType.Null) { return null; } TypeInfo typeInfo = clrType.GetTypeInfo(); if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>)) { clrType = typeInfo.GenericTypeArguments[0]; typeInfo = clrType.GetTypeInfo(); } if (clrType == typeof(string)) { return SQLite3.ColumnString(stmt, index); } if (clrType == typeof(int)) { return SQLite3.ColumnInt(stmt, index); } if (clrType == typeof(bool)) { return SQLite3.ColumnInt(stmt, index) == 1; } if (clrType == typeof(double)) { return SQLite3.ColumnDouble(stmt, index); } if (clrType == typeof(float)) { return (float)SQLite3.ColumnDouble(stmt, index); } if (clrType == typeof(TimeSpan)) { if (_conn.StoreTimeSpanAsTicks) { return new TimeSpan(SQLite3.ColumnInt64(stmt, index)); } string text = SQLite3.ColumnString(stmt, index); if (!TimeSpan.TryParseExact(text, "c", CultureInfo.InvariantCulture, TimeSpanStyles.None, out var result)) { result = TimeSpan.Parse(text); } return result; } if (clrType == typeof(DateTime)) { if (_conn.StoreDateTimeAsTicks) { return new DateTime(SQLite3.ColumnInt64(stmt, index)); } string s = SQLite3.ColumnString(stmt, index); if (!DateTime.TryParseExact(s, _conn.DateTimeStringFormat, CultureInfo.InvariantCulture, _conn.DateTimeStyle, out var result2)) { result2 = DateTime.Parse(s); } return result2; } if (clrType == typeof(DateTimeOffset)) { return new DateTimeOffset(SQLite3.ColumnInt64(stmt, index), TimeSpan.Zero); } if (typeInfo.IsEnum) { if (type == SQLite3.ColType.Text) { string text2 = SQLite3.ColumnString(stmt, index); return Enum.Parse(clrType, text2.ToString(), ignoreCase: true); } return SQLite3.ColumnInt(stmt, index); } if (clrType == typeof(long)) { return SQLite3.ColumnInt64(stmt, index); } if (clrType == typeof(ulong)) { return (ulong)SQLite3.ColumnInt64(stmt, index); } if (clrType == typeof(uint)) { return (uint)SQLite3.ColumnInt64(stmt, index); } if (clrType == typeof(decimal)) { return (decimal)SQLite3.ColumnDouble(stmt, index); } if (clrType == typeof(byte)) { return (byte)SQLite3.ColumnInt(stmt, index); } if (clrType == typeof(ushort)) { return (ushort)SQLite3.ColumnInt(stmt, index); } if (clrType == typeof(short)) { return (short)SQLite3.ColumnInt(stmt, index); } if (clrType == typeof(sbyte)) { return (sbyte)SQLite3.ColumnInt(stmt, index); } if (clrType == typeof(byte[])) { return SQLite3.ColumnByteArray(stmt, index); } if (clrType == typeof(Guid)) { string g = SQLite3.ColumnString(stmt, index); return new Guid(g); } if (clrType == typeof(Uri)) { string uriString = SQLite3.ColumnString(stmt, index); return new Uri(uriString); } if (clrType == typeof(StringBuilder)) { string value = SQLite3.ColumnString(stmt, index); return new StringBuilder(value); } if (clrType == typeof(UriBuilder)) { string uri = SQLite3.ColumnString(stmt, index); return new UriBuilder(uri); } throw new NotSupportedException("Don't know how to read " + clrType); } } internal class FastColumnSetter { internal static MethodInfo GetFastSetterMethodInfoUnsafe(Type mappedTy