private static void ImplementNetworkMessageSerializer(string intermediateAssembly, string[] referencedAssemblies) { // First generate a temporary assembly that contains the compiled protobuf serializer. Using // a precompiled serializer dramatically improves performance. File.Copy(intermediateAssembly, intermediateAssembly + ".NetworkSource.dll", true); var temporaryAssemblyName = intermediateAssembly + ".NetworkIntermediate.dll"; var context = new PreCompileContext(); context.AssemblyName = temporaryAssemblyName; context.ProbePaths.AddRange(referencedAssemblies.Select(Path.GetDirectoryName)); context.Inputs.Add(intermediateAssembly + ".NetworkSource.dll"); context.TypeName = "_NetworkSerializer"; context.Execute(); // If the file doesn't exist, there were no network types to generate. if (!File.Exists(temporaryAssemblyName)) { return; } // Otherwise, open the intermediate assembly and the temporary assembly and merge the serializer // into the intermediate assembly so we don't need a seperate DLL. try { var resolver = new PreloadedAssemblyResolver(); foreach (var reference in referencedAssemblies) { Console.WriteLine("Loading referenced assembly from " + reference + "..."); resolver.Load(reference); } var readSymbols = File.Exists(Path.Combine(Path.GetDirectoryName(intermediateAssembly) ?? string.Empty, Path.GetFileNameWithoutExtension(intermediateAssembly) + ".pdb")) || File.Exists(Path.Combine(Path.GetDirectoryName(intermediateAssembly) ?? string.Empty, Path.GetFileNameWithoutExtension(intermediateAssembly) + ".dll.mdb")); var temporaryAssembly = AssemblyDefinition.ReadAssembly(temporaryAssemblyName, new ReaderParameters { ReadSymbols = false, AssemblyResolver = resolver }); var targetAssembly = AssemblyDefinition.ReadAssembly(intermediateAssembly, new ReaderParameters { ReadSymbols = readSymbols, AssemblyResolver = resolver }); // This copies just enough for the protobuf serializer to copy across (e.g. // it doesn't support generics or anything fancy). var sourceType = temporaryAssembly.MainModule.GetType("_NetworkSerializer"); var targetType = new TypeDefinition("_NetworkSerializers", "<>GeneratedSerializer", sourceType.Attributes, targetAssembly.MainModule.Import(sourceType.BaseType)); targetAssembly.MainModule.Types.Add(targetType); CopyType(sourceType, targetType); try { targetAssembly.Write(intermediateAssembly, new WriterParameters { WriteSymbols = readSymbols }); Console.WriteLine("Saved modified assembly."); } catch (IOException) { Console.WriteLine("Unable to write new assembly file; is it in use by your IDE?"); } } finally { try { File.Delete(temporaryAssemblyName); } catch { } } }
public void ImplementNetworkMessageSerializer(string intermediateAssembly, string[] referencedAssemblies) { // First generate a temporary assembly that contains the compiled protobuf serializer. Using // a precompiled serializer dramatically improves performance. File.Copy(intermediateAssembly, intermediateAssembly + ".NetworkSource.dll", true); var temporaryAssemblyName = intermediateAssembly + ".NetworkIntermediate.dll"; var context = new PreCompileContext(); context.AssemblyName = temporaryAssemblyName; context.ProbePaths.AddRange(referencedAssemblies.Select(Path.GetDirectoryName)); context.Inputs.Add(intermediateAssembly + ".NetworkSource.dll"); context.TypeName = "_NetworkSerializer"; context.Execute(); // If the file doesn't exist, there were no network types to generate. if (!File.Exists(temporaryAssemblyName)) { return; } // Otherwise, open the intermediate assembly and the temporary assembly and merge the serializer // into the intermediate assembly so we don't need a seperate DLL. try { var resolver = new PreloadedAssemblyResolver(); foreach (var reference in referencedAssemblies) { Console.WriteLine("Loading referenced assembly from " + reference + "..."); resolver.Load(reference); } var readSymbols = File.Exists(Path.Combine(Path.GetDirectoryName(intermediateAssembly) ?? string.Empty, Path.GetFileNameWithoutExtension(intermediateAssembly) + ".pdb")) || File.Exists(Path.Combine(Path.GetDirectoryName(intermediateAssembly) ?? string.Empty, Path.GetFileNameWithoutExtension(intermediateAssembly) + ".dll.mdb")); var temporaryAssembly = AssemblyDefinition.ReadAssembly(temporaryAssemblyName, new ReaderParameters { ReadSymbols = false, AssemblyResolver = resolver }); var targetAssembly = AssemblyDefinition.ReadAssembly(intermediateAssembly, new ReaderParameters { ReadSymbols = readSymbols, AssemblyResolver = resolver }); // This copies just enough for the protobuf serializer to copy across (e.g. // it doesn't support generics or anything fancy). var sourceType = temporaryAssembly.MainModule.GetType("_NetworkSerializer"); var targetType = new TypeDefinition("_NetworkSerializers", "<>GeneratedSerializer", sourceType.Attributes, targetAssembly.MainModule.Import(sourceType.BaseType)); targetAssembly.MainModule.Types.Add(targetType); CopyType(sourceType, targetType); try { targetAssembly.Write(intermediateAssembly, new WriterParameters {WriteSymbols = readSymbols}); Console.WriteLine("Saved modified assembly."); } catch (IOException) { Console.WriteLine("Unable to write new assembly file; is it in use by your IDE?"); } } finally { try { File.Delete(temporaryAssemblyName); } catch { } } }