예제 #1
0
파일: FmbUtil.cs 프로젝트: 0x0ade/FmbLib
        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);
        }
예제 #2
0
파일: FmbUtil.cs 프로젝트: 0x0ade/FmbLib
        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);
        }
예제 #3
0
파일: FmbUtil.cs 프로젝트: 0x0ade/FmbLib
        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());
        }
예제 #4
0
        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);
            }
        }