update MetaID, add dublication exception

This commit is contained in:
Mikhail 2024-09-18 17:02:14 +08:00
parent d62dfed0d5
commit 639cd64cc7
2 changed files with 44 additions and 20 deletions

View File

@ -1,13 +1,12 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Runtime.InteropServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Interface, Inherited = false, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Interface, Inherited = false, AllowMultiple = false)]
public sealed class MetaIDAttribute : EcsMetaAttribute public sealed class MetaIDAttribute : EcsMetaAttribute
{ {
//private static HashSet<string> _ids = new HashSet<string>();
public readonly string ID; public readonly string ID;
public MetaIDAttribute(string id) public MetaIDAttribute(string id)
{ {
@ -19,33 +18,42 @@ namespace DCFApixels.DragonECS
{ {
Throw.ArgumentException($"Аргумент {nameof(id)} не может содержать символ запятой ','"); Throw.ArgumentException($"Аргумент {nameof(id)} не может содержать символ запятой ','");
} }
//if (_ids.Add(id) == false) //этот ексепшен не работает, так как атрибуты не кешируются а пересоздаются
//{
// //TODO перевести ексепшен
// Throw.ArgumentException($"Дублирование MetaID: {id}");
//}
ID = id; ID = id;
} }
} }
public static class MetaIDUtility public static class MetaIDUtility
{ {
[ThreadStatic]
private static System.Random _randon;
[ThreadStatic]
private static byte[] _buffer;
[ThreadStatic]
private static bool _isInit;
public static unsafe string GenerateNewUniqueID() public static unsafe string GenerateNewUniqueID()
{ {
long ticks = DateTime.Now.Ticks; if (_isInit == false)
byte* hibits = stackalloc byte[8];
hibits = (byte*)ticks;
byte[] byteArray = Guid.NewGuid().ToByteArray();
fixed (byte* ptr = byteArray)
{ {
for (int i = 0; i < 8; i++) IntPtr prt = Marshal.AllocHGlobal(1);
{ long alloc = (long)prt;
byteArray[i] = hibits[i]; Marshal.Release(prt);
} _randon = new System.Random((int)alloc);
_buffer = new byte[8];
_isInit = true;
} }
return BitConverter.ToString(byteArray).Replace("-", "");
byte* hibits = stackalloc byte[8];
long* hibitsL = (long*)hibits;
hibitsL[0] = DateTime.Now.Ticks;
hibitsL[1] = _randon.Next();
for (int i = 0; i < 8; i++)
{
_buffer[i] = hibits[i];
}
return BitConverter.ToString(_buffer).Replace("-", "");
} }
public static unsafe string GenerateNewUniqueIDWithAttribute() public static unsafe string GenerateNewUniqueIDWithAttribute()
{ {

View File

@ -461,11 +461,27 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region GetMetaID #region GetMetaID
#if (DEBUG && !DISABLE_DEBUG) || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
private static Dictionary<string, Type> _idTypePairs = new Dictionary<string, Type>();
#endif
public static string GetMetaID(Type type) public static string GetMetaID(Type type)
{ {
#if (DEBUG && !DISABLE_DEBUG) || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает #if (DEBUG && !DISABLE_DEBUG) || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
var atr = type.GetCustomAttribute<MetaIDAttribute>(); var atr = type.GetCustomAttribute<MetaIDAttribute>();
return atr != null ? atr.ID : string.Empty;
if (atr == null)
{
return string.Empty;
}
else
{
if (_idTypePairs.TryGetValue(atr.ID, out Type otherType) && type != otherType) //этот ексепшен не работает, так как атрибуты не кешируются а пересоздаются
{
Throw.Exception($"Types {type.Name} and {otherType.Name} have duplicate MetaID identifiers.");
}
_idTypePairs.Add(atr.ID, type);
return atr.ID;
}
#else #else
EcsDebug.PrintWarning($"Reflection is not available, the {nameof(MetaGenerator)}.{nameof(GetTags)} method does not work."); EcsDebug.PrintWarning($"Reflection is not available, the {nameof(MetaGenerator)}.{nameof(GetTags)} method does not work.");
return string.Empty; return string.Empty;