public static void GetGeneratedCode(Type keyType, Type payloadType, out string generatedClassName, out string expandedCode, out List <Assembly> assemblyReferences) { var template = new SafeBatchTemplate(); assemblyReferences = new List <Assembly> { Transformer.SystemRuntimeSerializationDll // needed for [DataContract] and [DataMember] in generated code }; assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(keyType)); template.keyType = keyType; assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(payloadType)); template.payloadType = payloadType; template.needsPolymorphismCheck = !payloadType.GetTypeInfo().IsValueType&& !payloadType.IsAnonymousTypeName() && !payloadType.GetTypeInfo().IsSealed; template.payloadMightBeNull = payloadType.CanContainNull(); generatedClassName = Transformer.GetBatchClassName(keyType, payloadType); template.CLASSNAME = generatedClassName.CleanUpIdentifierName(); generatedClassName = generatedClassName.AddNumberOfNecessaryGenericArguments(keyType, payloadType); var payloadRepresentation = new ColumnarRepresentation(payloadType); template.fields = payloadRepresentation.AllFields; template.noPublicFields = payloadRepresentation.noFields; expandedCode = template.TransformText(); }
/// <summary> /// Generate a batch class definition from the types <typeparamref name="TKey"/> and <typeparamref name="TPayload"/>. /// Compile the definition, dynamically load the assembly containing it, and return the Type representing the /// batch class. /// </summary> /// <typeparam name="TKey"> /// The key type for the batch class. /// </typeparam> /// <typeparam name="TPayload"> /// The payload type for which a batch class is generated. The batch class will have a field F of type T[] for every field /// F of type T in the type <typeparamref name="TPayload"/>. /// </typeparam> /// <returns> /// A type that is defined to be a subtype of Batch<<typeparamref name="TKey"/>,<typeparamref name="TPayload"/>>. /// </returns> public static Type GenerateBatchClass <TKey, TPayload>() { #if CODEGEN_TIMING Stopwatch sw = new Stopwatch(); sw.Start(); #endif var keyType = typeof(TKey); var payloadType = typeof(TPayload); SafeBatchTemplate.GetGeneratedCode(keyType, payloadType, out string generatedClassName, out string expandedCode, out List <Assembly> assemblyReferences); assemblyReferences.Add(MemoryManager.GetMemoryPool <TKey, TPayload>().GetType().GetTypeInfo().Assembly); assemblyReferences.Add(SystemRuntimeSerializationDll); if (keyType != typeof(Empty)) { assemblyReferences.Add(typeof(Empty).GetTypeInfo().Assembly); assemblyReferences.Add(StreamMessageManager.GetStreamMessageType <Empty, TPayload>().GetTypeInfo().Assembly); } var a = CompileSourceCode(expandedCode, assemblyReferences, out string errorMessages); var t = a.GetType(generatedClassName); if (t.GetTypeInfo().IsGenericType) { var list = keyType.GetAnonymousTypes(); list.AddRange(payloadType.GetAnonymousTypes()); t = t.MakeGenericType(list.ToArray()); } #if CODEGEN_TIMING sw.Stop(); Console.WriteLine("Time to generate and instantiate a batch for {0},{1}: {2}ms", keyType.GetCSharpSourceSyntax(), payload.GetCSharpSourceSyntax(), sw.ElapsedMilliseconds); #endif return(t); }