using System; using System.Collections.Generic; #if DEBUG && !PROFILER using System.Reflection; #endif using Svelto.DataStructures; using Svelto.ECS.Internal; using Svelto.Utilities; namespace Svelto.ECS { public class EntityBuilder : IEntityBuilder where T : IEntityStruct, new() { public EntityBuilder() { _initializer = default(T); #if DEBUG && !PROFILER if (needsReflection == false && typeof(T) != typeof(EntityInfoView)) { CheckFields(typeof(T)); } #endif if (needsReflection == true) { EntityView.InitCache(); } } #if DEBUG && !PROFILER static void CheckFields(Type type) { var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); for (int i = fields.Length - 1; i >= 0; --i) { var field = fields[i]; var fieldFieldType = field.FieldType; SubCheckFields(fieldFieldType); } if (type.Assembly == Assembly.GetCallingAssembly()) { var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); if (methods.Length > properties.Length + 1) throw new EntityStructException(type); for (int i = properties.Length - 1; i >= 0; --i) { var propertyInfo = properties[i]; var fieldFieldType = propertyInfo.PropertyType; SubCheckFields(fieldFieldType); } } } static void SubCheckFields(Type fieldFieldType) { if (fieldFieldType.IsPrimitive == true || fieldFieldType.IsValueType == true) { if (fieldFieldType.IsValueType && !fieldFieldType.IsEnum && fieldFieldType.IsPrimitive == false) { CheckFields(fieldFieldType); } return; } throw new EntityStructException(fieldFieldType); } #endif public void BuildEntityViewAndAddToList(ref ITypeSafeDictionary dictionary, EGID entityID, object[] implementors) { if (dictionary == null) dictionary = new TypeSafeDictionary(); var castedDic = dictionary as TypeSafeDictionary; if (needsReflection == true) { DBC.ECS.Check.Require(implementors != null, "Implementors not found while building an EntityView"); T lentityView; EntityView.BuildEntityView(entityID, out lentityView); this.FillEntityView(ref lentityView , entityViewBlazingFastReflection , implementors , DESCRIPTOR_NAME); castedDic.Add(entityID.entityID, ref lentityView); } else { _initializer.ID = entityID; castedDic.Add(entityID.entityID, _initializer); } } ITypeSafeDictionary IEntityBuilder.Preallocate(ref ITypeSafeDictionary dictionary, int size) { return Preallocate(ref dictionary, size); } public static ITypeSafeDictionary Preallocate(ref ITypeSafeDictionary dictionary, int size) { if (dictionary == null) dictionary = new TypeSafeDictionary(size); else dictionary.AddCapacity(size); return dictionary; } public Type GetEntityType() { return ENTITY_VIEW_TYPE; } static FasterList>> entityViewBlazingFastReflection { get { return EntityView.cachedFields; } } static readonly Type ENTITY_VIEW_TYPE = typeof(T); static readonly string DESCRIPTOR_NAME = ENTITY_VIEW_TYPE.ToString(); static readonly bool needsReflection = typeof(IEntityViewStruct).IsAssignableFrom(typeof(T)); internal T _initializer; } public class EntityStructException : Exception { public EntityStructException(Type fieldType):base("EntityStruct must contains only value types and no public methods! " + fieldType.ToString()) {} } }