// [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(); }
/// <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); }
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()); }