private static string getTypeName(string readerName, Type type) { string typeName; if (type != null) { typeName = type.Name; Type[] genericArgs = type.GetGenericArguments(); if (genericArgs.Length != 0) { typeName += "["; for (int i = 0; i < genericArgs.Length; i++) { typeName += "["; typeName += genericArgs[i].FullName; typeName += ", "; typeName += genericArgs[i].Assembly.GetName().Name; typeName += "]"; if (i != genericArgs.Length - 1) { typeName += ","; } } typeName += "]"; } } else { typeName = readerName; FmbHelper.Log("Input type name: " + typeName); if (typeName.Contains("Readers")) { //FmbHelper.Log("debug warning: " + typeName + " contains \"Readers\". In case of failure, debug."); typeName = typeName.Replace("Readers", "Riidars"); } if (typeName.Contains("[[")) { //generic instantiated type typeName = typeName.Substring(typeName.LastIndexOf(".", typeName.IndexOf("Reader")) + 1); typeName = typeName.Replace("Reader", ""); } else if (typeName.Contains("`")) { //generic type typeName = typeName.Substring(typeName.LastIndexOf(".") + 1); typeName = typeName.Replace("Reader", ""); } else if (typeName.Contains("Reader")) { //xna reader typeName = typeName.Substring(0, typeName.LastIndexOf("Reader")); typeName = typeName.Substring(typeName.LastIndexOf(".") + 1); } FmbHelper.Log("Got type name: " + typeName); } return(typeName); }
public static TypeHandler GenerateHandler(string readerName, Type type) { TypeHandler handler = null; string typeName = getTypeName(readerName, type); if (type == null) { type = FmbHelper.FindType(typeName); } FmbHelper.Log("Generating TypeHandler for " + typeName); Assembly assembly = Assembly.GetExecutingAssembly(); if (ManifestResourceNames == null) { ManifestResourceNames = assembly.GetManifestResourceNames(); } string path = null; string comparisonReader = typeName + "Reader.txt"; string comparisonHandler = typeName + "Handler.txt"; for (int i = 0; i < ManifestResourceNames.Length; i++) { if ( ManifestResourceNames[i].EndsWith(comparisonReader) || ManifestResourceNames[i].EndsWith(comparisonHandler) ) { path = ManifestResourceNames[i]; break; } } FmbHelper.Log("Generating TypeHandler<" + typeName + "> from " + path); string source; using (Stream s = assembly.GetManifestResourceStream(path)) { if (s == null) { FmbHelper.Log("Resource cannot be loaded."); return(null); } using (StreamReader sr = new StreamReader(s)) { source = GenerateHandlerSource(sr, typeName, type); } } CompilerParameters parameters = new CompilerParameters(); parameters.GenerateInMemory = true; parameters.CompilerOptions = "/optimize"; AssemblyName[] references = assembly.GetReferencedAssemblies(); for (int i = 0; i < references.Length; i++) { parameters.ReferencedAssemblies.Add(references[i].Name); } parameters.ReferencedAssemblies.Add(assembly.Location); for (int i = 0; i < GeneratedTypeHandlerAssemblies.Count; i++) { string reference = GeneratedTypeHandlerAssemblies[i]; if (parameters.ReferencedAssemblies.Contains(reference)) { continue; } parameters.ReferencedAssemblies.Add(reference); } using (CSharpCodeProvider provider = new CSharpCodeProvider()) { try { CompilerResults results = provider.CompileAssemblyFromSource(parameters, source); if (results.Errors.HasErrors) { FmbHelper.Log("Errors while generating TypeHandler:"); foreach (CompilerError error in results.Errors) { FmbHelper.Log(error.ToString()); } FmbHelper.Log("GeneratedTypeHandler source:"); FmbHelper.Log(source); FmbHelper.Log("Referenced assemblies:"); for (int i = 0; i < parameters.ReferencedAssemblies.Count; i++) { FmbHelper.Log(parameters.ReferencedAssemblies[i]); } } else { Type compiledType = results.CompiledAssembly.GetType("JIT" + typeName + "Handler"); handler = (TypeHandler)compiledType.GetConstructor(new Type[0]).Invoke(new object[0]); } } catch (Exception e) { FmbHelper.Log("Error while generating TypeHandler:"); FmbHelper.Log(e.ToString()); FmbHelper.Log("GeneratedTypeHandler source:"); FmbHelper.Log(source); FmbHelper.Log("Referenced assemblies:"); for (int i = 0; i < parameters.ReferencedAssemblies.Count; i++) { FmbHelper.Log(parameters.ReferencedAssemblies[i]); } } } return(handler); }
public static string GenerateHandlerSource(StreamReader sr, string typeName, Type type, string handlerName, string @namespace) { if (type == null) { type = FmbHelper.FindType(typeName); } if (type == null) { FmbHelper.Log("Type not found for handler to generate: " + typeName); } string tab = @namespace == null ? "" : "\t"; string usings = "using FmbLib;\nusing System;\nusing System.IO;\n"; StringBuilder readerBuilder = new StringBuilder(); StringBuilder writerBuilder = new StringBuilder(); string readerObjectConstruction = typeName + " obj = new " + typeName + "();\n"; string writerObjectCast = typeName + " obj = (" + typeName + ") obj_;\n"; bool usingsComplete = false; string line; while ((line = sr.ReadLine()) != null) { if (line.StartsWith("##")) { continue; } line = line.Trim(); if (line.Length == 0) { continue; } if (line.StartsWith("#if ")) { line = line.Substring(4); bool not = line.StartsWith("!"); if (not) { line = line.Substring(1); } if (line == "XNA") { line = "FmbUtil.IsXNA"; } else if (line == "UNITY") { line = "FmbUtil.IsUNITY"; } else if (line == "FEZENGINE") { line = "FmbUtil.IsFEZENGINE"; } else if (line == "TEST") { line = "FmbUtil.IsTEST"; } FmbHelper.AppendTo(tab, readerBuilder, writerBuilder); FmbHelper.AppendTo("\t\t", readerBuilder, writerBuilder); FmbHelper.AppendTo("if (", readerBuilder, writerBuilder); if (not) { FmbHelper.AppendTo("!", readerBuilder, writerBuilder); } FmbHelper.AppendTo(line, readerBuilder, writerBuilder); FmbHelper.AppendTo(") {\n", readerBuilder, writerBuilder); continue; } if (line == ("#endif")) { FmbHelper.AppendTo(tab, readerBuilder, writerBuilder); FmbHelper.AppendTo("\t\t}\n", readerBuilder, writerBuilder); continue; } if (!usingsComplete && line.StartsWith("using ")) { line = line.Substring(6, line.Length - 6 - 1); for (int i = 0; i < NamespaceRemap.Count; i++) { line = line.Replace(NamespaceRemap[i].Key, NamespaceRemap[i].Value); } line = "using " + line + ";\n"; if (!usings.Contains(line)) { usings += line; } continue; } usingsComplete = true; if (line.StartsWith("#rc ") || line.StartsWith("#wc ")) { bool read = !line.StartsWith("#wc "); line = line.Substring(4); if (read) { readerObjectConstruction = line + "\n"; } else { writerObjectCast = line + "\n"; } continue; } if (!line.Contains(" ") || line.StartsWith("#r ") || line.StartsWith("#w ")) { bool read = !line.StartsWith("#w "); if (line.StartsWith("#")) { line = line.Substring(3); } bool isMethod = type != null && type.GetMethod(line) != null; StringBuilder lineBuilder = read ? readerBuilder : writerBuilder; lineBuilder.Append(tab).Append("\t\t"); if (isMethod) { lineBuilder.Append("obj."); } lineBuilder.Append(line); if (isMethod) { lineBuilder.Append("();"); } lineBuilder.AppendLine(); continue; } FmbHelper.AppendTo(tab, readerBuilder, writerBuilder); FmbHelper.AppendTo("\t\t", readerBuilder, writerBuilder); int indexSplit = line.IndexOf(" "); string var = line.Substring(0, indexSplit); string binaryType = line.Substring(indexSplit + 1); readerBuilder.Append("obj.").Append(var).Append(" = "); if (binaryType.StartsWith("Object<")) { readerBuilder.Append("FmbUtil.Read").Append(binaryType).Append("(reader, xnb);"); } else if (GeneratedTypeHandlerSpecialTypes.Contains(binaryType)) { readerBuilder.Append("FmbUtil.ReadObject<").Append(binaryType).Append(">(reader, xnb, false);"); } else { readerBuilder.Append("reader.Read").Append(binaryType).Append("();"); } readerBuilder.AppendLine(); if (binaryType.StartsWith("Object<")) { writerBuilder.Append("FmbUtil.WriteObject(writer, obj.").Append(var); } else if (GeneratedTypeHandlerSpecialTypes.Contains(binaryType)) { writerBuilder.Append("FmbUtil.GetTypeHandler<").Append(binaryType).Append(">().Write(writer, obj.").Append(var); } else { writerBuilder.Append("writer.Write(obj.").Append(var); } writerBuilder.Append(");\n"); } StringBuilder builder = new StringBuilder() .AppendLine(usings); if (@namespace != null) { builder.Append("namespace ").Append(@namespace).AppendLine(" {"); } builder.Append(tab).Append("public class ").Append(handlerName).Append(" : TypeHandler<").Append(typeName).AppendLine("> {") .AppendLine() .Append(tab).AppendLine("\tpublic override object Read(BinaryReader reader, bool xnb) {") .Append(tab).Append("\t\t").AppendLine(readerObjectConstruction) .AppendLine(readerBuilder.ToString()) .Append(tab).AppendLine("\t\treturn obj;") .Append(tab).AppendLine("\t}") .AppendLine() .Append(tab).AppendLine("\tpublic override void Write(BinaryWriter writer, object obj_) {") .Append(tab).Append("\t\t").AppendLine(writerObjectCast) .Append(writerBuilder.ToString()) .Append(tab).AppendLine("\t}") .Append(tab).AppendLine("}"); if (@namespace != null) { builder.AppendLine("}"); } return(builder.ToString()); }
private static Type FindType_(string name, bool remappedNamespace) { Type type_ = null; if (CacheTypes.TryGetValue(name, out type_)) { return(type_); } if (CachePrefoundTypes.TryGetValue(name, out type_)) { CacheTypes[name] = type_; return(type_); } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); List <Assembly> delayedAssemblies = new List <Assembly>(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name.EndsWith(".mm") || BlacklistedAssemblies.Contains(assembly.GetName().Name)) { delayedAssemblies.Add(assembly); continue; } try { Type[] types = assembly.GetTypes(); foreach (Type type in types) { if ((type.Name == name && type.FullName.EndsWith("." + name)) || name == type.FullName) { CacheTypes[name] = type; return(type); } CachePrefoundTypes[type.FullName] = CachePrefoundTypes[type.Name] = type; } } catch (ReflectionTypeLoadException e) { FmbHelper.Log("Failed searching a type in XmlHelper's FindType."); FmbHelper.Log("Assembly: " + assembly.GetName().Name); FmbHelper.Log(e.Message); foreach (Exception le in e.LoaderExceptions) { FmbHelper.Log(le.Message); } } } foreach (Assembly assembly in delayedAssemblies) { try { Type[] types = assembly.GetTypes(); foreach (Type type in types) { if ((type.Name == name && type.FullName.EndsWith("." + name)) || name == type.FullName) { CacheTypes[name] = type; return(type); } } } catch (ReflectionTypeLoadException e) { FmbHelper.Log("Failed searching a type in XmlHelper's FindType."); FmbHelper.Log("Assembly: " + assembly.GetName().Name); FmbHelper.Log(e.Message); foreach (Exception le in e.LoaderExceptions) { FmbHelper.Log(le.Message); } } } if (!remappedNamespace) { string oldname = name; for (int i = 0; i < FmbUtil.NamespaceRemap.Count; i++) { name = name.Replace(FmbUtil.NamespaceRemap[i].Key, FmbUtil.NamespaceRemap[i].Value); } Type foundType = FindType_(name, true); CacheTypes[oldname] = foundType; return(foundType); } else { CacheTypes[name] = null; return(null); } }