Exemplo n.º 1
0
        // [Fact]
        public void ExportEverythingInExamples()
        {
            var path   = Path.ChangeExtension(nameof(ExportEverything), "dll");
            var except = new HashSet <Type>
            {
                typeof(Issue41.A_Orig),
                typeof(Issue41.B_Orig),
                typeof(WithIP),
                typeof(Examples.Issues.I),
                typeof(Examples.Issues.O),
                typeof(Examples.Issues.OS),
                typeof(Examples.Issues.C),
                typeof(Examples.Issues.CS),
                typeof(Issue509.Item),
                typeof(Issue509.ItemSurrogate),
                typeof(ImmutableCollections.ImmutableConcreteFields),
                typeof(ImmutableCollections.ImmutableConcreteProperties),
                typeof(ImmutableCollections.ImmutableInterfaceFields),
                typeof(ImmutableCollections.ImmutableInterfaceProperties),
                typeof(ProtoGeneration.MyNonSurrogate),
                typeof(ProtoGeneration.MySurrogate),
                typeof(ProtoGeneration.UsesSurrogates),
                typeof(StupidlyComplexModel.SimpleModel),
                typeof(AssortedGoLiveRegressions.HasBytes),
#if !NETCOREAPP3_1
                typeof(Issue124.TypeWithColor),
#endif
                typeof(Issue184.A),
                typeof(Issue184.B),
                typeof(Issue218.Test),
                typeof(Issue222.Foo),
                typeof(Issue222.Bar),
                typeof(Issue374.Issue374TestModel),
            };
            var options = new RuntimeTypeModel.CompilerOptions
            {
                TypeName = nameof(ExportEverything),
#pragma warning disable CS0618
                OutputPath = path,
#pragma warning restore CS0618
            };

            options.IncludeType += t =>
            {
                return(!except.Contains(t));
            };

            AutoCompileTypeModel.CreateForAssembly(GetType().Assembly, options);
            PEVerify.AssertValid(path);
        }
    private static void BuildMyProtoModel()
    {
        RuntimeTypeModel typeModel = GetModel();

        //typeModel.Compile("MyProtoModel", "MyProtoModel.dll");
        RuntimeTypeModel.CompilerOptions co = new RuntimeTypeModel.CompilerOptions();
        co.TypeName = "MyProtoModel";
        #pragma warning disable CS0618 // Type or member is obsolete
        co.OutputPath = "MyProtoModel.dll";
        #pragma warning restore CS0618 // Type or member is obsolete
        typeModel.Compile(co);

        if (!Directory.Exists("Assets/Plugins"))
        {
            Directory.CreateDirectory("Assets/Plugins");
        }

        File.Copy("MyProtoModel.dll", "Assets/Plugins/MyProtoModel.dll");

        AssetDatabase.Refresh();
    }
Exemplo n.º 3
0
        /// <summary>
        /// Perform the precompilation operation
        /// </summary>
        public bool Execute()
        {
            // model to work with
            var model = TypeModel.Create();

            model.Universe.AssemblyResolve += (sender, args) =>
            {
                string nameOnly = args.Name.Split(',')[0];

                if (nameOnly == "IKVM.Reflection" && args.RequestingAssembly != null && args.RequestingAssembly.FullName.StartsWith("protobuf-net"))
                {
                    throw new InvalidOperationException("This operation needs access to the protobuf-net.dll used by your library, **in addition to** the protobuf-net.dll that is included with the precompiler; the easiest way to do this is to ensure the referenced protobuf-net.dll is in the same folder as your library.");
                }
                var uni = model.Universe;
                foreach (var tmp in uni.GetAssemblies())
                {
                    if (tmp.GetName().Name == nameOnly)
                    {
                        return(tmp);
                    }
                }
                var asm = ResolveNewAssembly(uni, nameOnly + ".dll");
                if (asm != null)
                {
                    return(asm);
                }
                asm = ResolveNewAssembly(uni, nameOnly + ".exe");
                if (asm != null)
                {
                    return(asm);
                }

                throw new InvalidOperationException("All assemblies must be resolved explicity; did not resolve: " + args.Name);
            };
            bool allGood  = true;
            var  mscorlib = ResolveNewAssembly(model.Universe, "mscorlib.dll");

            if (mscorlib == null)
            {
                Console.Error.WriteLine("mscorlib.dll not found!");
                allGood = false;
            }
            ResolveNewAssembly(model.Universe, "System.dll"); // not so worried about whether that one exists...
            if (ResolveNewAssembly(model.Universe, "protobuf-net.dll") == null)
            {
                Console.Error.WriteLine("protobuf-net.dll not found!");
                allGood = false;
            }
            if (!allGood)
            {
                return(false);
            }
            var      assemblies = new List <IKVM.Reflection.Assembly>();
            MetaType metaType   = null;

            foreach (var file in inputs)
            {
                assemblies.Add(model.Load(file));
            }
            // scan for obvious protobuf types
            var attributeType = model.Universe.GetType("System.Attribute, mscorlib");
            var toAdd         = new List <IKVM.Reflection.Type>();

            foreach (var asm in assemblies)
            {
                foreach (var type in asm.GetTypes())
                {
                    bool add = false;
                    if (!(type.IsClass || type.IsValueType))
                    {
                        continue;
                    }

                    foreach (var attrib in type.__GetCustomAttributes(attributeType, true))
                    {
                        string name = attrib.Constructor.DeclaringType.FullName;
                        switch (name)
                        {
                        case "ProtoBuf.ProtoContractAttribute":
                            add = true;
                            break;
                        }
                        if (add)
                        {
                            break;
                        }
                    }
                    if (add)
                    {
                        toAdd.Add(type);
                    }
                }
            }

            if (toAdd.Count == 0)
            {
                Console.Error.WriteLine("No [ProtoContract] types found; nothing to do!");
                return(false);
            }

            // find surrogate directives
            for (int i = 0; i < toAdd.Count; i++)
            {
                var type = toAdd[i];
                if (type.Name.ToLower().Contains("surrogatedirectives"))
                {
                    foreach (var field in type.GetFields())
                    {
                        var sourceType = FindSurrogateSourceType(field.FieldType, model.Universe);
                        if (sourceType != null)
                        {
                            Console.WriteLine("Adding " + sourceType.FullName + " with surrogate " + field.FieldType + "...");
                            model.Add(sourceType, false).SetSurrogate(field.FieldType);
                        }
                    }
                    toAdd.RemoveAt(i);
                    i -= 1;
                }
            }
            // add everything we explicitly know about
            toAdd.Sort((x, y) => string.Compare(x.FullName, y.FullName));
            foreach (var type in toAdd)
            {
                Console.WriteLine("Adding " + type.FullName + "...");
                var tmp = model.Add(type, true);
                if (metaType == null)
                {
                    metaType = tmp;                   // use this as the template for the framework version
                }
            }
            // find surrogates from toAdd
            if (AutoSurrogate)
            {
                foreach (var type in toAdd)
                {
                    if (!type.Name.ToLower().Contains("surrogate"))
                    {
                        continue;
                    }
                    var sourceType = FindSurrogateSourceType(type, model.Universe);
                    if (sourceType != null)
                    {
                        try
                        {
                            model.Add(sourceType, false).SetSurrogate(type);
                            Console.WriteLine("Adding " + sourceType.FullName + " with surrogate " + type.FullName + "...");
                        }
                        catch (InvalidOperationException)
                        {
                            // Ignore InvalidOperationException that can be caused by modification frozen type
                        }
                    }
                }
            }
            // add everything else we can find
            model.Cascade();
            var inferred = new List <IKVM.Reflection.Type>();

            foreach (MetaType type in model.GetTypes())
            {
                if (!toAdd.Contains(type.Type))
                {
                    inferred.Add(type.Type);
                }
            }
            inferred.Sort((x, y) => string.Compare(x.FullName, y.FullName));
            foreach (var type in inferred)
            {
                Console.WriteLine("Adding " + type.FullName + "...");
            }
            // find surrogates from cascaded ones
            if (AutoSurrogate)
            {
                foreach (MetaType type in model.GetTypes())
                {
                    if (!type.Type.Name.ToLower().Contains("surrogate"))
                    {
                        continue;
                    }
                    var sourceType = FindSurrogateSourceType(type.Type, model.Universe);
                    if (sourceType != null)
                    {
                        try
                        {
                            model.Add(sourceType, false).SetSurrogate(type.Type);
                            Console.WriteLine("Adding " + sourceType.FullName + " with surrogate " + type.Type.FullName + "...");
                        }
                        catch (InvalidOperationException)
                        {
                            // Ignore InvalidOperationException that can be caused by modification frozen type
                        }
                    }
                }
            }

            // configure the output file/serializer name, and borrow the framework particulars from
            // the type we loaded
            var options = new RuntimeTypeModel.CompilerOptions
            {
                TypeName            = TypeName,
                OutputPath          = AssemblyName,
                ImageRuntimeVersion = mscorlib.ImageRuntimeVersion,
                MetaDataVersion     = 0x20000, // use .NET 2 onwards
                KeyContainer        = KeyContainer,
                KeyFile             = KeyFile,
                PublicKey           = PublicKey
            };

            if (mscorlib.ImageRuntimeVersion == "v1.1.4322")
            { // .NET 1.1-style
                options.MetaDataVersion = 0x10000;
            }
            if (metaType != null)
            {
                options.SetFrameworkOptions(metaType);
            }
            options.Accessibility = this.Accessibility;
            Console.WriteLine("Compiling " + options.TypeName + " to " + options.OutputPath + "...");
            // GO WORK YOUR MAGIC, CRAZY THING!!
            model.Compile(options);
            Console.WriteLine("All done");

            return(true);
        }
Exemplo n.º 4
0
        public static void PrecompileSerializer(string outputPath)
        {
            if (EditorApplication.isCompiling)
            {
                Debug.LogWarning("The precompiled serializer canot be created while Unity is " +
                                 "compiling code. Please try again once compilation has finished.");
                return;
            }
            if (_decompilationProcess != null)
            {
                Debug.LogWarning("A prior precompiled serializer process is still running.");
                return;
            }

            string TypeName = ProtoBufNetSettings.PrecompiledSerializerTypeName;
            string DllPath  = TypeName + ".dll";

            var options = new RuntimeTypeModel.CompilerOptions {
                TypeName            = TypeName,
                OutputPath          = DllPath,
                ImageRuntimeVersion = Assembly.GetExecutingAssembly().ImageRuntimeVersion,
                MetaDataVersion     = 0x20000, // use .NET 2 onwards
                Accessibility       = RuntimeTypeModel.Accessibility.Public
            };

            // Create the precompiled serializer
            var model = TypeModelCreator.CreateModel();

            try {
                model.Compile(options);

                var output = new StringBuilder();
                output.AppendLine("Created protobuf-net serialization DLL (at " +
                                  Path.GetFullPath(DllPath) + "). It contains serialization data for the " +
                                  "following types:");
                foreach (var modelType in model.GetTypes())
                {
                    output.Append('\t');
                    output.AppendLine(modelType.ToString());
                }
                Debug.Log(output.ToString());
            }
            catch (Exception) {
                Debug.LogError("Make sure to compile to protobuf-net DLL while the editor is " +
                               "not in AOT mode");
                throw;
            }

            // Run the decompiler
            var searchPaths = new List <string>()
            {
                Path.GetDirectoryName(typeof(CommonBaseBehavior).Assembly.Location), // Scripts (Assembly-CSharp and the like)
                Path.GetDirectoryName(typeof(UnityEngine.Object).Assembly.Location), // UnityEngine.dll
            };

            searchPaths.AddRange(from string directory in Directory.GetDirectories("Assets" + Path.DirectorySeparatorChar, "*", SearchOption.AllDirectories)
                                 where (directory.Contains("/.") || directory.Contains("\\.")) == false
                                 where Directory.GetFiles(directory, "*.dll").Count() > 0
                                 select Path.GetFullPath(directory));

            DllPath    = Path.GetFullPath(DllPath);
            outputPath = Path.GetFullPath(outputPath);

            RunDecompiler(outputPath, DllPath, searchPaths.ToArray());
        }