在开发过程遇到了需要将多选枚举序列化读取和写入的问题,搜了半天也没有好的解决方案.这里就自己写个吧
1.多选的枚举数值设置:
[System.Flags]
public enum BigTypes
{
Type1=1,
Type2=2,
Type3=4,
Type4=8,
Type5=16,
Type6=64
}
因为多选枚举的多选是位运算,这样设置数值才能保证多选不出现异常,实际测试也符合这一点
2.需要给需要多选的枚举增加特性标签
需要自己写个类继承PropertyAttribute,不能直接继承PropertyAttribute
然后给枚举带上特性标签
public class EnumFlags : PropertyAttribute
{
}
[EnumFlags]
public BigTypes bigType;
3.多选枚举序列化字符串
多选枚举Tostring()后会变成用","分隔的字符串,当然有两个特殊数值
tostring()后值的内容如下:
选择Noting,值为"0",
选择Everything后值为"-1",
选择单个Type1,值为"Type1",
选择多个值为"Type1,Type2"
以此类推
我们得到序列化的代码:
/// <summary>
/// 输出多选枚举的值
/// </summary>
/// <param name="bigType"></param>
private void OutPutMultEnumValue(ref BigTypes bigTypes)
{
string [] enumFlags = bigTypes.ToString().Split(',');
if (enumFlags.Length==1)
{
if (enumFlags[0]=="0")
{
Debug.Log("当前什么内容都没选");
}
else if(enumFlags[0]=="-1")
{
Debug.Log("当前内容全选了");
}
}
strValue = bigTypes.ToString();
}
4.多选枚举数据加载
多选枚举加载的数据格式通过上面的形式得到,那么我们加载反推就好
多选枚举增加一个枚举使用|运算,减少使用&运算,由此得到下面的代码
/// <summary>
/// 读取多选枚举的值,Enum.Tostring()后的值为","分隔的字符串
/// </summary>
/// <param name="strValue"></param>
private void OnReadMultEnumValue( ref BigTypes currEnum,string strValue)
{
string [] enumFlags = strValue.ToString().Split(',');
foreach (var value in enumFlags)
{
currEnum|=(BigTypes)Enum.Parse(typeof(BigTypes) , value);
}
}
5.完整代码
using System;
using UnityEngine;
using UnityEngine.UI;
namespace Test
{
public class EnumNormalTest : MonoBehaviour
{
[EnumFlags]
public BigTypes bigType;
public Text _txtEnumInfo;
public string strValue = "0";//当前序列化值
private void Update()
{
if (Input.GetKeyDown(KeyCode.O))
{
ReadEnum();
}
else if(Input.GetKeyDown(KeyCode.I))
{
WriteEnum();
}
else if(Input.GetKeyDown(KeyCode.P))
{
ClearEnum();
}
}
/// <summary>
/// 读取多选枚举的值
/// </summary>
public void ReadEnum()
{
Debug.Log("读取多选枚举的值");
OnReadMultEnumValue(ref bigType,strValue);
_txtEnumInfo.text = strValue;
}
/// <summary>
/// 写入多选枚举的值
/// </summary>
public void WriteEnum()
{
Debug.Log("写入多选枚举的值");
OutPutMultEnumValue(ref bigType);
_txtEnumInfo.text = strValue;
}
/// <summary>
/// 清理选择
/// </summary>
public void ClearEnum()
{
ClearMultEnum(ref bigType);
_txtEnumInfo.text = "";
}
/// <summary>
/// 读取多选枚举的值,Enum.Tostring()后的值为","分隔的字符串
/// </summary>
/// <param name="strValue"></param>
private void OnReadMultEnumValue( ref BigTypes currEnum,string strValue)
{
currEnum = 0;
string [] enumFlags = strValue.ToString().Split(',');
foreach (var value in enumFlags)
{
currEnum|=(BigTypes)Enum.Parse(typeof(BigTypes) , value);
}
}
private void ClearMultEnum(ref BigTypes currEnum)
{
currEnum = 0;
}
/// <summary>
/// 输出多选枚举的值
/// </summary>
/// <param name="bigType"></param>
private void OutPutMultEnumValue(ref BigTypes bigTypes)
{
string [] enumFlags = bigTypes.ToString().Split(',');
if (enumFlags.Length==1)
{
if (enumFlags[0]=="0")
{
Debug.Log("当前什么内容都没选");
}
else if(enumFlags[0]=="-1")
{
Debug.Log("当前内容全选了");
}
}
strValue = bigTypes.ToString();
}
}
[System.Flags]
public enum BigTypes
{
Type1=1,
Type2=2,
Type3=4,
Type4=8,
Type5=16,
Type6=64
}
public class EnumFlags : PropertyAttribute
{
}
}
6.其他需要注意的点
定义的枚举上要带上System.Flags的特性标签
枚举是值类型,所以在方法内赋值要带上ref才行
|