private static void DefineTypes() { var watch = Stopwatch.StartNew(); var assembly = Assembly.GetExecutingAssembly(); IEnumerable <Type> types; try { types = assembly.GetTypes(); } catch (ReflectionTypeLoadException e) { types = e.Types.Where(x => x is not null) !; } var engineRelatedTypes = types.Where(t => t?.IsClass == true && t.Namespace?.StartsWith("GBX.NET.Engines") == true); var availableClassesByType = new Dictionary <Type, uint>(); foreach (var type in engineRelatedTypes) { if (!type.IsSubclassOf(typeof(CMwNod)) && type != typeof(CMwNod)) // Engine types { continue; } var id = type.GetCustomAttribute <NodeAttribute>()?.ID; if (!id.HasValue) { throw new Exception($"{type.Name} misses NodeAttribute."); } AvailableClasses.Add(id.Value, type); availableClassesByType.Add(type, id.Value); } foreach (var typePair in AvailableClasses) { var id = typePair.Key; var type = typePair.Value; var classes = new List <uint>(); Type currentType = type.BaseType !; while (currentType != typeof(object)) { classes.Add(availableClassesByType[currentType]); currentType = currentType.BaseType !; } AvailableInheritanceClasses[type] = classes; var chunks = type.GetNestedTypes().Where(x => x.IsSubclassOf(typeof(Chunk))); var baseType = type.BaseType !; while (baseType !.IsSubclassOf(typeof(CMwNod))) { chunks = chunks.Concat(baseType.GetNestedTypes().Where(x => x.IsSubclassOf(typeof(Chunk)))); baseType = baseType.BaseType; } var availableChunkClasses = new Dictionary <uint, Type>(); var availableHeaderChunkClasses = new Dictionary <uint, Type>(); foreach (var chunk in chunks) { var chunkAttribute = chunk.GetCustomAttribute <ChunkAttribute>(); if (chunkAttribute == null) { throw new Exception($"Chunk {chunk.FullName} doesn't have ChunkAttribute."); } if (chunk.GetInterface(nameof(IHeaderChunk)) == null) { availableChunkClasses.Add(chunkAttribute.ID, chunk); } else { availableHeaderChunkClasses.Add(chunkAttribute.ID, chunk); } } AvailableChunkClasses.Add(type, availableChunkClasses); AvailableHeaderChunkClasses.Add(type, availableHeaderChunkClasses); } foreach (var idClassPair in AvailableClasses) { var id = idClassPair.Key; var classType = idClassPair.Value; AvailableClassAttributes.Add(classType, classType.GetCustomAttributes()); } foreach (var classChunksPair in AvailableHeaderChunkClasses.Concat(AvailableChunkClasses)) { var attributeDictionary = new Dictionary <uint, IEnumerable <Attribute> >(); foreach (var chunkClassIdTypePair in classChunksPair.Value) { var id = chunkClassIdTypePair.Key; var chunkClass = chunkClassIdTypePair.Value; var attributes = chunkClass.GetCustomAttributes(); attributeDictionary[id] = attributes; AvailableChunkAttributesByType[chunkClass] = attributes; } AvailableChunkAttributes[classChunksPair.Key] = attributeDictionary; } foreach (var idClassPair in AvailableClasses) { var id = idClassPair.Key; var classType = idClassPair.Value; var privateConstructor = classType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Array.Empty <Type>(), null); if (privateConstructor is null) { throw new PrivateConstructorNotFoundException(classType); } var newExp = Expression.New(privateConstructor); var lambda = Expression.Lambda <Func <CMwNod> >(newExp); var compiled = lambda.Compile(); AvailableClassConstructors.Add(id, compiled); } foreach (var classChunksPair in AvailableChunkClasses) { var constructors = GetChunkConstructors(classChunksPair); if (constructors != null) { AvailableChunkConstructors[classChunksPair.Key] = constructors; } } foreach (var classChunksPair in AvailableHeaderChunkClasses) { var constructors = GetChunkConstructors(classChunksPair); if (constructors != null) { AvailableHeaderChunkConstructors[classChunksPair.Key] = constructors; } } Debug.WriteLine("Types defined in " + watch.Elapsed.TotalMilliseconds + "ms"); }
private static void DefineTypes() { var watch = Stopwatch.StartNew(); var assembly = Assembly.GetExecutingAssembly(); IEnumerable <Type> types; try { types = assembly.GetTypes(); } catch (ReflectionTypeLoadException e) { types = e.Types; } var engineRelatedTypes = types.Where(t => t?.IsClass == true && t.Namespace?.StartsWith("GBX.NET.Engines") == true); var availableClassesByType = new Dictionary <Type, uint>(); foreach (var type in engineRelatedTypes) { if (type.IsSubclassOf(typeof(CMwNod)) || type == typeof(CMwNod)) // Engine types { var id = type.GetCustomAttribute <NodeAttribute>()?.ID; if (id.HasValue) { AvailableClasses.Add(id.Value, type); availableClassesByType.Add(type, id.Value); } else { throw new Exception($"{type.Name} misses NodeAttribute."); } } } var availableInheritanceTypes = new Dictionary <Type, List <Type> >(); foreach (var typePair in AvailableClasses) { var id = typePair.Key; var type = typePair.Value; List <uint> classes = new List <uint>(); List <Type> inheritedTypes = new List <Type>(); Type currentType = type.BaseType; while (currentType != typeof(object)) { classes.Add(availableClassesByType[currentType]); inheritedTypes.Add(currentType); currentType = currentType.BaseType; } AvailableInheritanceClasses[type] = classes; availableInheritanceTypes[type] = inheritedTypes; var chunks = type.GetNestedTypes().Where(x => x.IsSubclassOf(typeof(Chunk))); var availableChunkClasses = new Dictionary <uint, Type>(); var availableHeaderChunkClasses = new Dictionary <uint, Type>(); foreach (var chunk in chunks) { var chunkAttribute = chunk.GetCustomAttribute <ChunkAttribute>(); if (chunkAttribute == null) { throw new Exception($"Chunk {chunk.FullName} doesn't have ChunkAttribute."); } if (chunk.GetInterface(nameof(IHeaderChunk)) == null) { availableChunkClasses.Add(chunkAttribute.ID, chunk); } else { availableHeaderChunkClasses.Add(chunkAttribute.ID, chunk); } } AvailableChunkClasses.Add(type, availableChunkClasses); AvailableHeaderChunkClasses.Add(type, availableHeaderChunkClasses); } foreach (var typePair in availableInheritanceTypes) { var mainType = typePair.Key; foreach (var type in typePair.Value) { foreach (var chunkType in AvailableChunkClasses[type]) { AvailableChunkClasses[mainType][chunkType.Key] = chunkType.Value; } } } Debug.WriteLine("Types defined in " + watch.Elapsed.TotalMilliseconds + "ms"); }