| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- using System;
- using System.IO;
- using System.Diagnostics;
- using System.Collections.Generic;
- using System.Collections.Immutable;
- using System.Linq;
- using System.Reflection;
- using System.Reflection.Metadata;
- using System.Reflection.PortableExecutable;
- using System.Reflection.Metadata.Ecma335;
- using System.Text;
- using AtomicEngine;
- using File = System.IO.File;
- namespace AtomicTools
- {
- class AssemblyInspector
- {
- Dictionary<string, InspectorEnum> InspectorEnums = new Dictionary<string, InspectorEnum>();
- Dictionary<string, InspectorComponent> InspectorComponents = new Dictionary<string, InspectorComponent>();
- PEReader peFile;
- MetadataReader metaReader;
- public AssemblyInspector()
- {
- }
- public string DumpToJSON()
- {
- var dict = new Dictionary<string, object>();
- var enumList = new List<object>();
- var componentList = new List<object>();
- foreach (var entry in InspectorEnums)
- {
- enumList.Add(entry.Value.GetJSONDict());
- }
- foreach (var entry in InspectorComponents)
- {
- componentList.Add(entry.Value.GetJSONDict());
- }
- dict["enums"] = enumList;
- dict["components"] = componentList;
- return MiniJSON.Json.Serialize(dict);
- }
- public void Inspect(String pathToAssembly)
- {
- using (var stream = File.OpenRead(pathToAssembly))
- using (peFile = new PEReader(stream))
- {
- metaReader = peFile.GetMetadataReader();
- ParseEnums();
- ParseComponents();
- }
- }
- void ParseComponents()
- {
- foreach (var handle in metaReader.TypeDefinitions)
- {
- var typeDef = metaReader.GetTypeDefinition(handle);
- // Is this a generic type?
- var genericParams = typeDef.GetGenericParameters();
- if (genericParams.Count != 0)
- continue;
- var typeName = metaReader.GetString(typeDef.Name);
- var baseTypeHandle = typeDef.BaseType;
- // Work up to base reference (ie defined outside this assembly)
- while (baseTypeHandle.Kind == HandleKind.TypeDefinition)
- {
- var baseTypeDef = metaReader.GetTypeDefinition((TypeDefinitionHandle)baseTypeHandle);
- // No way to predetermine if .BaseType is valid
- try
- {
- baseTypeHandle = baseTypeDef.BaseType;
- }
- catch (Exception) { break; }
- }
- if (baseTypeHandle.Kind == HandleKind.TypeReference)
- {
- var typeRef = metaReader.GetTypeReference((TypeReferenceHandle)baseTypeHandle);
- var baseName = metaReader.GetString(typeRef.Name);
- if (baseName != "CSComponent")
- continue;
- var inspector = new CSComponentInspector(typeDef, peFile, metaReader);
- var icomponent = inspector.Inspect();
- if (icomponent != null)
- InspectorComponents[icomponent.Name] = icomponent;
- }
- }
- }
- void ParseEnums()
- {
- foreach (var handle in metaReader.TypeDefinitions)
- {
- var typeDef = metaReader.GetTypeDefinition(handle);
- var baseTypeHandle = typeDef.BaseType;
- if (baseTypeHandle.Kind == HandleKind.TypeReference)
- {
- var typeRef = metaReader.GetTypeReference((TypeReferenceHandle)baseTypeHandle);
- if (metaReader.GetString(typeRef.Name) == "Enum")
- {
- ParseEnum(typeDef);
- }
- }
- }
- }
- void ParseEnum(TypeDefinition enumTypeDef)
- {
- // TODO: verify that int32 is the enums storage type for constant read below
- InspectorEnum ienum = new InspectorEnum();
- ienum.Name = metaReader.GetString(enumTypeDef.Name);
- InspectorEnums[ienum.Name] = ienum;
- var fields = enumTypeDef.GetFields();
- foreach (var fieldHandle in fields)
- {
- var inspectorField = new InspectorField();
- var fieldDef = metaReader.GetFieldDefinition(fieldHandle);
- if ((fieldDef.Attributes & FieldAttributes.HasDefault) != 0)
- {
- var constantHandle = fieldDef.GetDefaultValue();
- var constant = metaReader.GetConstant(constantHandle);
- BlobReader constantReader = metaReader.GetBlobReader(constant.Value);
- ienum.Values[metaReader.GetString(fieldDef.Name)] = constantReader.ReadInt32();
- }
- }
- return;
- }
- }
- internal class InspectorEnum
- {
- public String Name;
- public Dictionary<string, int> Values = new Dictionary<string, int>();
- public Dictionary<string, object> GetJSONDict()
- {
- var dict = new Dictionary<string, object>();
- dict["name"] = Name;
- dict["values"] = Values;
- return dict;
- }
- }
- internal class InspectorComponent
- {
- public String Name;
- public String Namespace;
- public Dictionary<string, InspectorField> Fields = new Dictionary<string, InspectorField>();
- public Dictionary<string, object> GetJSONDict()
- {
- var dict = new Dictionary<string, object>();
- dict["name"] = Name;
- dict["namespace"] = Namespace;
- var fieldList = new List<object>();
- foreach (var entry in Fields)
- {
- fieldList.Add(entry.Value.GetJSONDict());
- }
- dict["fields"] = fieldList;
- return dict;
- }
- }
- internal class InspectorField
- {
- public Dictionary<string, object> GetJSONDict()
- {
- var dict = new Dictionary<string, object>();
- dict["isEnum"] = IsEnum;
- dict["isArray"] = IsArray;
- dict["typeName"] = TypeName;
- dict["name"] = Name;
- dict["defaultValue"] = DefaultValue;
- dict["caPos"] = CustomAttrPositionalArgs;
- dict["caNamed"] = CustomAttrNamedArgs;
- return dict;
- }
- public bool IsEnum = false;
- public bool IsArray = false;
- public string TypeName;
- // the Name of the InspectorField
- public string Name;
- // The DefaultValue if supplied
- public string DefaultValue;
- // custom attributes, positional and named
- public List<string> CustomAttrPositionalArgs = new List<string>();
- public Dictionary<string, string> CustomAttrNamedArgs = new Dictionary<string, string>();
- }
- }
|