Skip to content

Commit

Permalink
v1.0.143 新增 BindableDictionary 及 Example、文档
Browse files Browse the repository at this point in the history
  • Loading branch information
liangxiegame committed Sep 19, 2024
1 parent 1486953 commit e0b0885
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"Id": "",
"Version": "v1.0.142",
"Version": "v1.0.143",
"Type": 0,
"AccessRight": 0,
"DownloadUrl": "",
Expand All @@ -11,10 +11,10 @@
],
"DocUrl": "https://liangxiegame.com",
"Readme": {
"version": "v1.0.142",
"content": "增加 BindableList &文档&Example",
"version": "v1.0.143",
"content": "新增 BindableDictionary 及 Example、文档",
"author": "liangxie",
"date": "2024 年 09 月 18 日 14:41",
"date": "2024 年 09 月 19 日 14:21",
"PackageId": ""
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/****************************************************************************
* Copyright (c) 2016 - 2024 liangxiegame UNDER MIT License
*
* https://qframework.cn
* https://github.com/liangxiegame/QFramework
* https://gitee.com/liangxiegame/QFramework
****************************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace QFramework
{
[Serializable]
public class BindableDictionary<TKey, TValue> : IDictionary<TKey, TValue>,
IDictionary,ISerializable, IDeserializationCallback
{
private readonly Dictionary<TKey, TValue> mInner;

public BindableDictionary() => mInner = new Dictionary<TKey, TValue>();
public BindableDictionary(IEqualityComparer<TKey> comparer) => mInner = new Dictionary<TKey, TValue>(comparer);
public BindableDictionary(Dictionary<TKey, TValue> innerDictionary) => mInner = innerDictionary;

public TValue this[TKey key]
{
get => mInner[key];
set
{
TValue oldValue;
if (TryGetValue(key, out oldValue))
{
mInner[key] = value;
mOnReplace?.Trigger(key, oldValue, value);
}
else
{
mInner[key] = value;
mOnAdd?.Trigger(key, value);
mOnCountChanged?.Trigger(Count);
}
}
}



public int Count => mInner.Count;
public Dictionary<TKey, TValue>.KeyCollection Keys => mInner.Keys;
public Dictionary<TKey, TValue>.ValueCollection Values => mInner.Values;

public void Add(TKey key, TValue value)
{
mInner.Add(key, value);

mOnAdd?.Trigger(key, value);
mOnCountChanged?.Trigger(Count);
}

public void Clear()
{
var beforeCount = Count;
mInner.Clear();

mOnClear?.Trigger();
if (beforeCount > 0)
{
mOnCountChanged?.Trigger(Count);
}
}

public bool Remove(TKey key)
{
TValue oldValue;
if (mInner.TryGetValue(key, out oldValue))
{
var isSuccessRemove = mInner.Remove(key);
if (isSuccessRemove)
{
mOnRemove?.Trigger(key, oldValue);
mOnCountChanged?.Trigger(Count);
}
return isSuccessRemove;
}

return false;
}

public bool ContainsKey(TKey key) => mInner.ContainsKey(key);

public bool TryGetValue(TKey key, out TValue value) => mInner.TryGetValue(key, out value);

public Dictionary<TKey, TValue>.Enumerator GetEnumerator() => mInner.GetEnumerator();


[NonSerialized]
private EasyEvent<int> mOnCountChanged;
public EasyEvent<int> OnCountChanged => mOnCountChanged ?? (mOnCountChanged = new EasyEvent<int>());


[NonSerialized]
private EasyEvent mOnClear;
public EasyEvent OnClear => mOnClear ?? (mOnClear = new EasyEvent());

[NonSerialized]
private EasyEvent<TKey, TValue> mOnAdd;
public EasyEvent<TKey, TValue> OnAdd => mOnAdd ?? (mOnAdd = new EasyEvent<TKey, TValue>());

[NonSerialized]
private EasyEvent<TKey,TValue> mOnRemove;
public EasyEvent<TKey, TValue> OnRemove => mOnRemove ?? (mOnRemove = new EasyEvent<TKey, TValue>());

[NonSerialized]
private EasyEvent<TKey, TValue,TValue> mOnReplace;

/// <summary>
/// TKey:key
/// TValue:oldValue
/// TValue:newValue
/// </summary>
public EasyEvent<TKey, TValue,TValue> OnReplace => mOnReplace ?? (mOnReplace = new EasyEvent<TKey, TValue, TValue>());



#region implement explicit
object IDictionary.this[object key]
{
get => this[(TKey)key];
set => this[(TKey)key] = (TValue)value;
}
bool IDictionary.IsFixedSize => ((IDictionary)mInner).IsFixedSize;

bool IDictionary.IsReadOnly => ((IDictionary)mInner).IsReadOnly;

bool ICollection.IsSynchronized => ((IDictionary)mInner).IsSynchronized;

ICollection IDictionary.Keys => ((IDictionary)mInner).Keys;

object ICollection.SyncRoot => ((IDictionary)mInner).SyncRoot;

ICollection IDictionary.Values => ((IDictionary)mInner).Values;

bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => ((ICollection<KeyValuePair<TKey, TValue>>)mInner).IsReadOnly;

ICollection<TKey> IDictionary<TKey, TValue>.Keys => mInner.Keys;

ICollection<TValue> IDictionary<TKey, TValue>.Values => mInner.Values;

void IDictionary.Add(object key, object value) => Add((TKey)key, (TValue)value);

bool IDictionary.Contains(object key) => ((IDictionary)mInner).Contains(key);

void ICollection.CopyTo(Array array, int index) => ((IDictionary)mInner).CopyTo(array, index);

public void GetObjectData(SerializationInfo info, StreamingContext context) => ((ISerializable)mInner).GetObjectData(info, context);

public void OnDeserialization(object sender) => ((IDeserializationCallback)mInner).OnDeserialization(sender);

void IDictionary.Remove(object key) => Remove((TKey)key);

void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);

bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) => ((ICollection<KeyValuePair<TKey, TValue>>)mInner).Contains(item);

void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => ((ICollection<KeyValuePair<TKey, TValue>>)mInner).CopyTo(array, arrayIndex);

IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() => ((ICollection<KeyValuePair<TKey, TValue>>)mInner).GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => mInner.GetEnumerator();

bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
TValue v;
if (TryGetValue(item.Key, out v))
{
if (EqualityComparer<TValue>.Default.Equals(v, item.Value))
{
Remove(item.Key);
return true;
}
}

return false;
}

IDictionaryEnumerator IDictionary.GetEnumerator() => ((IDictionary)mInner).GetEnumerator();

#endregion
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 20240918. 新增 BindableList 功能
# 20240918. 新增 BindableList

BindableProperty 很好用,但是不支持 List 等集合。

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# 20240919. 新增 BindableDictionary

虽然笔者目前还不知道 BindableDictionary 能用在什么使用场景下,但是还是应童鞋的要求实现了 BindableDictionary。

基本使用如下:

``` csharp
using System.Linq;
using UnityEngine;

namespace QFramework.Example
{
public class BindableDictionaryExample : MonoBehaviour
{
private BindableDictionary<string, string> mDictionary = new BindableDictionary<string, string>();

private void Start()
{
mDictionary.OnCountChanged.Register(count =>
{
print("count:" + count);
}).UnRegisterWhenGameObjectDestroyed(gameObject);

mDictionary.OnAdd.Register((key, value) =>
{
print("add:" + key + "," + value);
}).UnRegisterWhenGameObjectDestroyed(gameObject);

mDictionary.OnRemove.Register((key, value) =>
{
print("remove:" + key + "," + value);
}).UnRegisterWhenGameObjectDestroyed(gameObject);

mDictionary.OnReplace.Register((key, oldValue,newValue) =>
{
print("replace:" + key + "," + oldValue + "," + newValue);
}).UnRegisterWhenGameObjectDestroyed(gameObject);

mDictionary.OnClear.Register(() =>
{
print("clear");
}).UnRegisterWhenGameObjectDestroyed(gameObject);
}

private string mKeyToDelete = null;
private void OnGUI()
{
IMGUIHelper.SetDesignResolution(640,360);

GUILayout.Label("Count:" + mDictionary.Count);
GUILayout.BeginVertical("box");

foreach (var kv in mDictionary)
{
GUILayout.BeginHorizontal("box");
GUILayout.Label($"{kv.Key},{kv.Value}");
if (GUILayout.Button("-"))
{
mKeyToDelete = kv.Key;
}

GUILayout.EndHorizontal();
}

if (GUILayout.Button("add"))
{
var key = "key" + Random.Range(0, 100);
if (!mDictionary.ContainsKey(key))
{
mDictionary.Add("key" + Random.Range(0,100),"value" + Random.Range(0,100));
}
}

if (mDictionary.Count > 0)
{
if (GUILayout.Button("remove"))
{
mDictionary.Remove(mDictionary.Keys.First());
}

if (GUILayout.Button("replace"))
{
mDictionary[mDictionary.Keys.First()] = "replaced value" + Random.Range(0, 100);
}

if (GUILayout.Button("clear"))
{
mDictionary.Clear();
}
}

GUILayout.EndVertical();




if (mKeyToDelete.IsNotNullAndEmpty())
{
mDictionary.Remove(mKeyToDelete);
mKeyToDelete = null;
}
}
}
}

```

运行结果如下:
![178a650f-97ee-44de-8f5c-447a853cdb6b](https://file.liangxiegame.com/178a650f-97ee-44de-8f5c-447a853cdb6b.gif)

输出结果如下:
![b8a5eb15-42cc-4c2d-9e5e-dff54e2a10e2](https://file.liangxiegame.com/b8a5eb15-42cc-4c2d-9e5e-dff54e2a10e2.png)

本文由 QFramework 教程年会员赞助,地址:[https://www.gamepixedu.com/goods/show/55](https://www.gamepixedu.com/goods/show/55)

* QFramework 主页:[qframework.cn](https://qframework.cn)
* QFramework 交流群: 623597263
* QFramework Github 地址: <https://github.com/liangxiegame/qframework>
* QFramework Gitee 地址:<https://gitee.com/liangxiegame/QFramework>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e0b0885

Please sign in to comment.