public GeneratorResult Generate(MethodCreatorCreator methodCreatorCreator) { #region Declare Value Type Serializer Methods var valueTypeSerializerType = methodCreatorCreator.Create("ValueTypeSerializer"); var valueTypeDeserializerType = methodCreatorCreator.Create("ValueTypeDeserializer"); var generatedValueTypeSerializeMethods = new Dictionary <Type, MethodInfo>(); var generatedValueTypeDeserializeMethods = new Dictionary <Type, MethodInfo>(); foreach (var valueType in typeClassifier.ValueTypes) { if (customMethods.HasTypeSerializer(valueType)) { continue; // Don't generate serializers where custom methods exist } var serializeMethod = valueTypeSerializerType.CreateMethod(valueType, "ValueTypeSerialize", typeof(void), new[] { typeof(SerializeContext), typeof(BinaryWriter), valueType.MakeByRefType() }); generatedValueTypeSerializeMethods.Add(valueType, serializeMethod); var deserializeMethod = valueTypeDeserializerType.CreateMethod(valueType, "ValueTypeDeserialize", typeof(void), new[] { typeof(DeserializeContext), typeof(BinaryReader), valueType.MakeByRefType() }); generatedValueTypeDeserializeMethods.Add(valueType, deserializeMethod); } #endregion #region Declare Reference Type Serializer Methods // Note: These methods have no type check/dispatch - fields that could reference derived types must go through the field methods instead of these! var referenceTypeSerializerType = methodCreatorCreator.Create("ReferenceTypeSerializer"); var referenceTypeDeserializerType = methodCreatorCreator.Create("ReferenceTypeDeserializer"); var generatedReferenceTypeSerializeMethods = new Dictionary <Type, MethodInfo>(); var generatedReferenceTypeDeserializeMethods = new Dictionary <Type, MethodInfo>(); foreach (var referenceType in typeClassifier.ReferenceTypes) { Debug.Assert(!referenceType.IsArray); if (customMethods.HasTypeSerializer(referenceType)) { continue; // Don't generate serializers where custom methods exist } var serializeMethod = referenceTypeSerializerType.CreateMethod(referenceType, "ReferenceTypeSerialize", typeof(void), new[] { typeof(SerializeContext), typeof(BinaryWriter), referenceType }); generatedReferenceTypeSerializeMethods.Add(referenceType, serializeMethod); var deserializeMethod = referenceTypeDeserializerType.CreateMethod(referenceType, "ReferenceTypeDeserialize", typeof(void), new[] { typeof(DeserializeContext), typeof(BinaryReader), referenceType }); generatedReferenceTypeDeserializeMethods.Add(referenceType, deserializeMethod); } #endregion #region Declare Field Serializer Methods var fieldSerializerType = methodCreatorCreator.Create("FieldSerializer"); var fieldDeserializerType = methodCreatorCreator.Create("FieldDeserializer"); var generatedReferenceFieldSerializeMethods = new Dictionary <Type, MethodInfo>(); var generatedReferenceFieldDeserializeMethods = new Dictionary <Type, MethodInfo>(); foreach (var fieldType in typeClassifier.fieldSerializerDispatchLookup.Keys) { if (customMethods.HasFieldSerializer(fieldType)) { continue; // Don't create field serializers where custom ones exist } var serializeMethod = fieldSerializerType.CreateMethod(fieldType, "FieldSerialize", typeof(void), new[] { typeof(SerializeContext), typeof(BinaryWriter), fieldType }); generatedReferenceFieldSerializeMethods.Add(fieldType, serializeMethod); var deserializeMethod = fieldDeserializerType.CreateMethod(fieldType, "FieldDeserialize", typeof(void), new[] { typeof(DeserializeContext), typeof(BinaryReader), fieldType.MakeByRefType() }); generatedReferenceFieldDeserializeMethods.Add(fieldType, deserializeMethod); } #endregion #region Declare Dispatch Methods var serializerDispatchType = methodCreatorCreator.Create("SerializerDispatch"); var deserializerDispatchType = methodCreatorCreator.Create("DeserializerDispatch"); // These are dispatched by ID#, so this is a lookup by that ID# var dynamicDispatchMethods = new List <SerializationMethods>(typeClassifier.dispatchableTypes.Count); // Dispatch to types that require actual dispatch (from type classification) as well as any suplemental types // (Suplemental types come from delegates, at the moment, a few of which require dynamic dispatch (see DelegateSerialization.SerializeDelegate) // and I haven't written a direct-dispatch path yet) HashSet <Type> dispatchTypes; if (suplementalDispatchTypes == null) { dispatchTypes = typeClassifier.dispatchableTypes; } else { dispatchTypes = new HashSet <Type>(typeClassifier.dispatchableTypes.Concat(suplementalDispatchTypes)); } foreach (var type in dispatchTypes.NetworkOrder(t => t.Module.Name + t.FullName)) { var idString = dynamicDispatchMethods.Count.ToString("0000"); SerializationMethods sm; sm.type = type; sm.serializer = serializerDispatchType.CreateMethod(type, "SerializeWithId_" + idString, typeof(void), new[] { typeof(SerializeContext), typeof(BinaryWriter), typeof(object) }); sm.deserializer = deserializerDispatchType.CreateMethod(type, "DeserializeFromId_" + idString, type, new[] { typeof(DeserializeContext), typeof(BinaryReader) }); dynamicDispatchMethods.Add(sm); // Defines the ID# } // Deserialization dispatch method (this could reasonably use a table like serialization, but it was original a giant switch statement - so let's keep it that way) deserializationDispatcherMethod = deserializerDispatchType.CreateMethod(null, "DeserializationDispatcher", typeof(object), new[] { typeof(DeserializeContext), typeof(BinaryReader) }); #endregion #region Lookup Hookup // These are all used to do lookup during IL generation (should probably be switched to a SerializationMethodProviders) fieldSerializeMethods = FallbackMethodProvider.Combine(customMethods.ValueTypeSerializeMethods, customMethods.ReferenceFieldSerializeMethods, new LookupMethodProvider(generatedValueTypeSerializeMethods), new LookupMethodProvider(generatedReferenceFieldSerializeMethods)); fieldDeserializeMethods = FallbackMethodProvider.Combine( customMethods.ValueTypeDeserializeMethods, customMethods.ReferenceFieldDeserializeMethods, new LookupMethodProvider(generatedValueTypeDeserializeMethods), new LookupMethodProvider(generatedReferenceFieldDeserializeMethods)); referenceTypeSerializeMethods = FallbackMethodProvider.Combine( customMethods.ReferenceTypeSerializeMethods, new LookupMethodProvider(generatedReferenceTypeSerializeMethods)); referenceTypeDeserializeMethods = FallbackMethodProvider.Combine( customMethods.ReferenceTypeDeserializeMethods, new LookupMethodProvider(generatedReferenceTypeDeserializeMethods)); var serializeContext = new ILGenContext(Direction.Serialize, fieldSerializeMethods, referenceTypeSerializeMethods); var deserializeContext = new ILGenContext(Direction.Deserialize, fieldDeserializeMethods, referenceTypeDeserializeMethods); #endregion #region Generate Dynamic Dispatch Method IL for (var i = 0; i < dynamicDispatchMethods.Count; i++) { // SerializeWithId Method: #region Generate IL { var il = dynamicDispatchMethods[i].serializer.GetILGenerator(); // br.Write('i'); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Callvirt, Methods.BinaryWriter_WriteInt32); // ReferenceTypeSerializer.Serialize(context, bw, (Class)obj); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Castclass, dynamicDispatchMethods[i].type); il.Emit(OpCodes.Call, referenceTypeSerializeMethods[dynamicDispatchMethods[i].type]); il.Emit(OpCodes.Ret); } #endregion // DeserializeFromId Method: #region Generate IL { var il = dynamicDispatchMethods[i].deserializer.GetILGenerator(); il.DeclareLocal(dynamicDispatchMethods[i].type); // Class obj // Class obj = /* create object */ GenerateTypeCreation(il, dynamicDispatchMethods[i].type); il.Emit(OpCodes.Stloc_0); // ReferenceTypeDeserializer.Deserialize(context, br, (Class)obj); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, referenceTypeDeserializeMethods[dynamicDispatchMethods[i].type]); // return obj; il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ret); } #endregion } #endregion #region Generate Reference Field Serializer Method IL foreach (var fieldDispatch in typeClassifier.fieldSerializerDispatchLookup) { var fieldType = fieldDispatch.Key; var dispatchToTypes = fieldDispatch.Value; var serializeMethod = generatedReferenceFieldSerializeMethods[fieldType]; var deserializeMethod = generatedReferenceFieldDeserializeMethods[fieldType]; GenerateReferenceFieldSerializer(serializeMethod.GetILGenerator(), fieldType, dispatchToTypes); GenerateReferenceFieldDeserializer(deserializeMethod.GetILGenerator(), fieldType, dispatchToTypes); } #endregion #region Generate Reference and Value Type Serializers foreach (var sm in generatedValueTypeSerializeMethods) { TypeSerializeILGeneration.GenerateValueTypeSerializationMethod(sm.Key, sm.Value.GetILGenerator(), serializeContext); } foreach (var sm in generatedValueTypeDeserializeMethods) { TypeSerializeILGeneration.GenerateValueTypeSerializationMethod(sm.Key, sm.Value.GetILGenerator(), deserializeContext); } foreach (var sm in generatedReferenceTypeSerializeMethods) { TypeSerializeILGeneration.GenerateReferenceTypeSerializationMethod(sm.Key, sm.Value.GetILGenerator(), serializeContext); } foreach (var sm in generatedReferenceTypeDeserializeMethods) { TypeSerializeILGeneration.GenerateReferenceTypeSerializationMethod(sm.Key, sm.Value.GetILGenerator(), deserializeContext); } #endregion #region Generate Deserialization Dispatcher (IL) { var il = deserializationDispatcherMethod.GetILGenerator(); var dispatchLabels = new Label[dynamicDispatchMethods.Count]; for (var i = 0; i < dispatchLabels.Length; i++) { dispatchLabels[i] = il.DefineLabel(); } var failLabel = il.DefineLabel(); // br.ReadInt32() il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Callvirt, typeof(BinaryReader) .GetMethod("ReadInt32")); // NOTE: C# compiler loads this into two locals for no reason // switch(...) il.Emit(OpCodes.Switch, dispatchLabels); il.Emit(OpCodes.Br, failLabel); // default case // NOTE: C# compiler emits br.s, but I bet it's not short with our huge table! for (var i = 0; i < dynamicDispatchMethods.Count; i++) { // case 'i': il.MarkLabel(dispatchLabels[i]); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, dynamicDispatchMethods[i].deserializer); il.Emit(OpCodes.Ret); } // throw new Exception("..."); il.MarkLabel(failLabel); il.Emit(OpCodes.Ldstr, "Unknown Type"); il.Emit(OpCodes.Newobj, typeof(Exception).GetConstructor(new[] { typeof(string) })); il.Emit(OpCodes.Throw); } #endregion #region Fill Serialization Dispatch Table // We used to generate a table with IL in the serializer assembly (fancy). Now we can just do it directly. // (But we do have to do it last, so the methods are actually ready to convert to delegates) var dispatchTable = new Dictionary <Type, SerializeDispatchDelegate>(); // Only dynamic methods can be converted to delegates (because the dynamic assembly we create in assembly-generating mode is save-only) if (methodCreatorCreator is DynamicMethodCreatorCreator) { for (var i = 0; i < dynamicDispatchMethods.Count; i++) { var serializerMethod = dynamicDispatchMethods[i].serializer as DynamicMethod; Debug.Assert(serializerMethod != null); var serializerDelegate = (SerializeDispatchDelegate)serializerMethod.CreateDelegate(typeof(SerializeDispatchDelegate)); dispatchTable.Add(dynamicDispatchMethods[i].type, serializerDelegate); } } #endregion #region Return var generatedMethodProviders = new SerializationMethodProviders( new LookupMethodProvider(generatedValueTypeSerializeMethods), new LookupMethodProvider(generatedValueTypeDeserializeMethods), new LookupMethodProvider(generatedReferenceTypeSerializeMethods), new LookupMethodProvider(generatedReferenceTypeDeserializeMethods), new LookupMethodProvider(generatedReferenceFieldSerializeMethods), new LookupMethodProvider(generatedReferenceFieldDeserializeMethods), new EmptyMethodProvider()); // Note: custom methods come before generated methods: var combinedMethodProviders = SerializationMethodProviders .Combine(customMethods, generatedMethodProviders); DeserializeDispatchDelegate deserializeDispatchDelegate = null; if (methodCreatorCreator is DynamicMethodCreatorCreator ) // Only dynamic methods can be converted to delegates (our dynamic assembly is save-only) { deserializeDispatchDelegate = (DeserializeDispatchDelegate)(deserializationDispatcherMethod as DynamicMethod).CreateDelegate( typeof(DeserializeDispatchDelegate)); } return(new GeneratorResult(combinedMethodProviders, dispatchTable, deserializeDispatchDelegate, null)); // module table gets filled later #endregion }
public static GeneratorResult Run(Assembly[] assemblies, Type[] predefinedRoots, GeneratorReports reports, bool createAssembly, string outputAssemblyName) { var baseLocation = assemblies.First() .Location; // <- should probably use all passed assemblies as potential base locations (also detect accidently passing a system one) if (baseLocation == "") // <- loaded from embedded resources { baseLocation = null; } else { baseLocation = Path.GetDirectoryName(baseLocation); } #region Initial Reporting - Assembly Info if (reports != null) { reports.Log.WriteLine(DateTime.Now); reports.Log.WriteLine(); reports.Log.WriteLine("Initial Assemblies (" + assemblies.Count() + ")"); foreach (var a in assemblies) { reports.Log.WriteLine(" " + a); } reports.Log.WriteLine(); reports.Log.WriteLine("Base Location = " + baseLocation ?? "<<resources>>"); reports.Log.WriteLine(); } #endregion #region Search for [SerializationRoot] attributes var rootTypes = new HashSet <Type>(); foreach (var assembly in assemblies) { var types = assembly.GetTypes(); foreach (var type in types.Where(t => t.GetCustomAttributes(typeof(SerializationRootAttribute), false).Length > 0)) { rootTypes.Add(type); } } if (predefinedRoots != null) { foreach (var type in predefinedRoots) { rootTypes.Add(type); } } if (reports != null) { reports.Log.WriteLine("Initial roots (" + rootTypes.Count + ")"); foreach (var type in rootTypes) { reports.Log.WriteLine(" " + type); } reports.Log.WriteLine(); } #endregion #region Custom Method Discovery if (reports != null) { reports.Log.WriteLine("Running custom method discovery"); } var customMethodAssemblies = new HashSet <Assembly>(assemblies); customMethodAssemblies.Add(typeof(SerializeList) .Assembly); // <- Get the assembly that contains all our "built-in" serializers var customMethods = CustomMethodDiscovery.Run(customMethodAssemblies, reports != null ? reports.CustomMethodDiscovery : null, reports != null ? reports.Error : null); // Attach hard-coded array serializer methods: customMethods = SerializationMethodProviders.Combine(SerializeArray.CreateSerializationMethodProviders(), customMethods); #endregion #region Type Discovery - First Pass var td = new TypeDiscovery(customMethods, assemblies); if (reports != null) { reports.Log.WriteLine("Running Type Discovery - First Pass"); reports.TypeDiscovery.WriteLine("---------------------------"); reports.TypeDiscovery.WriteLine("TYPE DISCOVERY - FIRST PASS"); reports.TypeDiscovery.WriteLine("---------------------------"); reports.TypeDiscovery.WriteLine(); } td.DiscoverFromRoots(rootTypes, reports != null ? reports.TypeDiscovery : null, reports != null ? reports.Error : null); #endregion #region Delegate Discovery and Type Discovery Second Pass List <DelegateUsage> delegateDiscoveryResult = null; IEnumerable <Type> allDelegateTargetTypes = null; if (td.FoundDelegates) { Debug.WriteLine("IMPORTANT: Serializer generator is doing delegate discovery! May be undesireable."); #region Delegate Discovery if (reports != null) { reports.Log.WriteLine("Running Delegate Discovery"); } // Only search for delegates in our own assemblies: var delegateDiscoveryAssemblies = td.Assemblies.Where(a => a.IsOurAssembly(baseLocation)); if (reports != null) { reports.DelegateDiscovery.WriteLine("Searching in assemblies:"); foreach (var a in delegateDiscoveryAssemblies) { reports.DelegateDiscovery.WriteLine(" " + a); } reports.DelegateDiscovery.WriteLine(); reports.DelegateDiscovery.WriteLine(); } delegateDiscoveryResult = DelegateDiscovery.Run(delegateDiscoveryAssemblies, reports != null ? reports.DelegateDiscovery : null, reports != null ? reports.Error : null); if (reports != null) { DelegateDiscovery.WriteDelegateUsageGrouped(delegateDiscoveryResult, reports.DelegateDiscoveryGrouped); } #endregion #region Type Discovery - Second Pass if (reports != null) { reports.Log.WriteLine("Running Type Discovery - Second Pass"); reports.TypeDiscovery.WriteLine("----------------------------"); reports.TypeDiscovery.WriteLine("TYPE DISCOVERY - SECOND PASS"); reports.TypeDiscovery.WriteLine("----------------------------"); reports.TypeDiscovery.WriteLine(); } allDelegateTargetTypes = delegateDiscoveryResult.Select(du => du.targetType) .Where(t => t != null) // <- Disregard delegates with static targets .Distinct(); td.DiscoverFromRoots(allDelegateTargetTypes, reports != null ? reports.TypeDiscovery : null, reports != null ? reports.Error : null); #endregion } else { if (reports != null) { reports.Log.WriteLine("Was able to skip delegate discovery!"); } } #endregion #region Type Classification if (reports != null) { reports.Log.WriteLine("Running type classification"); } var tc = new TypeClassifier(td); tc.RunClassification(); if (reports != null) { tc.WriteReport(reports.TypeClassification, reports.Error); CustomMethodDiscovery.CheckForDerivedCustomInitializers(customMethods.ReferenceTypeInitializeMethods, tc.ReferenceTypes, reports.Error); } #endregion #region Delegate Classification Dictionary <Type, DelegateTypeInfo> delegateTypeTable = null; if (delegateDiscoveryResult != null) { var dc = new DelegateClassification(td.delegateFieldTypes, delegateDiscoveryResult); delegateTypeTable = dc.GenerateDelegateTypeTable(); if (reports != null) { dc.Report(reports.DelegateClassification, reports.Error); // NOTE: Any methods that appear in this list consitute a security risk, as they can be sent across the network! // Make sure that all these methods are "safe" (nothing that can, say, access the filesystem) foreach (var methodName in delegateTypeTable.SelectMany(dt => dt.Value.methodInfoList) .Select(mi => mi.method).Distinct() .Select(m => m.DeclaringType + "." + m.Name).OrderBy(s => s)) { reports.DelegateMethods.WriteLine(methodName); } } // Attach delegate serializer method generator // NOTE: Doing this after type discovery, which automatically ignores delegates anyway, but before IL generation, which requires the methods to call // NOTE: Generated delegate serializers come *after* custom methods, because the user may specify custom serialization for any given delegate customMethods = SerializationMethodProviders.Combine(customMethods, DelegateSerialization.CreateSerializationMethodProviders()); } #endregion #region Module Table var moduleTable = td.Assemblies.Where(a => a.IsOurAssembly(baseLocation)).SelectMany(a => a.GetModules()) .NetworkOrder(module => module.Name).ToList(); #endregion #region Report Final Log Info if (reports != null) { reports.Log.WriteLine(); reports.Log.WriteLine(); var outsideTypes = td.valueTypes.Concat(td.referenceTypes) .Select(t => (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable <>) ? t.GetGenericArguments()[0] : t)) .Where(t => !customMethods.HasTypeSerializer(t)) .Where(t => !t.Assembly.IsOurAssembly(baseLocation)); reports.Log.WriteLine("Types outside of \"" + baseLocation + "\" without custom serializers (" + outsideTypes.Count() + ")"); foreach (var type in outsideTypes) { reports.Log.WriteLine(" " + type); } reports.Log.WriteLine(); if (delegateDiscoveryResult != null) { var openConstructedDelegates = delegateDiscoveryResult.Where(d => d.delegateType.ContainsGenericParameters || d.delegateMethod.ContainsGenericParameters); reports.Log.WriteLine("Open constructed delegates (" + openConstructedDelegates.Count() + ")"); foreach (var d in openConstructedDelegates) { reports.Log.WriteLine(" " + d.delegateType + " -> " + d.delegateMethod + " -> " + (d.targetType != null ? d.targetType.ToString() : "(null)")); } reports.Log.WriteLine(); } reports.Log.WriteLine(); reports.Log.WriteLine("Assemblies (" + td.Assemblies.Count() + ")"); foreach (var a in td.Assemblies) { reports.Log.WriteLine(" " + a); } reports.Log.WriteLine(); reports.Log.WriteLine(); reports.Log.WriteLine("Module Table (" + moduleTable.Count() + ")"); foreach (var module in moduleTable) { reports.Log.WriteLine(" " + module); } reports.Log.WriteLine(); var notInInitialAssemblies = td.Assemblies.Where(a => a.IsOurAssembly(baseLocation)) .Where(a => !assemblies.Contains(a)); if (notInInitialAssemblies.Count() > 0) { reports.Error.WriteLine("WARNING: Visited assemblies in \"" + baseLocation + "\" that were not in initial list of assemblies (see log for suggested command line)"); reports.Error.WriteLine( " (It is possible that custom serialize methods, delegate instantiations, and derived types in these assemblies were missed)"); foreach (var a in notInInitialAssemblies) { reports.Error.WriteLine(" " + a); } reports.Error.WriteLine(); } reports.Log.WriteLine(); reports.Log.WriteLine("Suggested initial assemblies for command line:"); foreach (var a in td.Assemblies.Where(a => a.IsOurAssembly(baseLocation))) { reports.Log.Write("\"" + a.Location + "\" "); } reports.Log.WriteLine(); reports.Log.WriteLine(); // Final Counts: if (delegateDiscoveryResult != null) { reports.Log.WriteLine(); reports.Log.WriteLine("Delegate Usage Count = " + delegateDiscoveryResult.Count); reports.Log.WriteLine("Distinct Delegate Method Count = " + delegateDiscoveryResult.Select(du => du.delegateMethod).Distinct().Count()); reports.Log.WriteLine("Distinct Delegate Target Type Count = " + delegateDiscoveryResult.Select(du => du.targetType).Distinct().Count()); } reports.Log.WriteLine(); reports.Log.WriteLine("Total Serializable Type Count = " + (td.referenceTypes.Count + td.valueTypes.Count)); reports.Log.WriteLine(); reports.Log.WriteLine(); } #endregion #region Generate Assembly var serializerMethodGenerator = new SerializerMethodGenerator(tc, customMethods, allDelegateTargetTypes); GeneratorResult generatorResult; if (createAssembly) { if (reports != null) { reports.Log.WriteLine("Generating assembly..."); } #if NET40 || NET45 || NET462 var an = new AssemblyName(outputAssemblyName); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save); var moduleBuilder = assemblyBuilder.DefineDynamicModule(outputAssemblyName + ".dll"); var methodCreatorCreator = new MethodBuilderCreatorCreator(moduleBuilder, "GenSerialize"); generatorResult = serializerMethodGenerator.Generate(methodCreatorCreator); methodCreatorCreator.Finish(); assemblyBuilder.Save(outputAssemblyName + ".dll"); #else // https://github.com/dotnet/roslyn/issues/10881 // https://github.com/dotnet/corert/tree/master/src/ILVerify throw new NotSupportedException("Cannot convert dynamic assembly to disk bytes in Roslyn without parsing a syntax tree!"); AssemblyName an = new AssemblyName(outputAssemblyName); AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndCollect); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(outputAssemblyName + ".dll"); var methodCreatorCreator = new MethodBuilderCreatorCreator(moduleBuilder, "GenSerialize"); generatorResult = serializerMethodGenerator.Generate(methodCreatorCreator); methodCreatorCreator.Finish(); Assembly assembly = moduleBuilder.Assembly; var compilation = CSharpCompilation.Create(outputAssemblyName); #endif } else { if (reports != null) { reports.Log.WriteLine("Generating dynamic methods..."); } var methodCreatorCreator = new DynamicMethodCreatorCreator(); generatorResult = serializerMethodGenerator.Generate(methodCreatorCreator); } if (reports != null) { reports.Log.WriteLine(); reports.Log.WriteLine("Done!"); } #endregion generatorResult.delegateTypeTable = delegateTypeTable; generatorResult.moduleTable = moduleTable; return(generatorResult); }