Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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());
        }
Exemplo n.º 3
0
        private static TypeHandler getHandler(string readerName, Type type)
        {
            string typeName = getTypeName(readerName, type);
            string handlerName;

            //TODO check if enum, ...
            if (type == null)
            {
                type = FmbHelper.FindType(typeName);
            }
            if (type == null && typeName.Contains("[["))
            {
                type = FmbHelper.FindType(typeName.Substring(0, typeName.IndexOf("[[")));
            }
            if (type != null && type.IsEnum)
            {
                return(FmbHelper.GetGenericTypeHandler(typeof(EnumHandler <>), type));
            }
            if (type != null && type.IsArray)
            {
                return(FmbHelper.GetGenericTypeHandler(typeof(ArrayHandler <>), type.GetElementType()));
            }

            //FmbHelper.Log("Getting TypeHandler for " + typeName);

            Type[] types = Assembly.GetExecutingAssembly().GetTypes();

            //FmbHelper.Log("typeName: " + typeName);

            if (typeName.Contains("[[") || (type != null && type.IsGenericType))
            {
                int length = typeName.IndexOf("[[");
                if (length < 0)
                {
                    length = typeName.Length;
                }
                handlerName = typeName.Substring(0, typeName.IndexOf("`")) + "Handler" + typeName.Substring(typeName.IndexOf("`"), length - typeName.IndexOf("`"));

                List <Type> genericParams = FmbHelper.GetGenericParamTypes(typeName);
                for (int i = 0; i < types.Length; i++)
                {
                    string typeName_ = getTypeName(types[i].Name, null);
                    if (typeName_ == handlerName && types[i].GetGenericArguments().Length == genericParams.Count)
                    {
                        return((TypeHandler)types[i].MakeGenericType(genericParams.ToArray()).GetConstructor(new Type[0]).Invoke(new object[0]));
                    }
                }

                return(null);
            }

            handlerName = typeName + "Handler";

            for (int i = 0; i < types.Length; i++)
            {
                if (getTypeName(types[i].Name, null) == handlerName)
                {
                    //FmbHelper.Log("Found " + types[i].Name);
                    return((TypeHandler)types[i].GetConstructor(new Type[0]).Invoke(new object[0]));
                }
            }

            return(null);
        }