/// <summary> /// Generate a batch class definition to be used as a Union pipe. /// Compile the definition, dynamically load the assembly containing it, and return the Type representing the /// union pipe class. /// </summary> /// <typeparam name="TKey">The key type for both sides.</typeparam> /// <typeparam name="TPayload">The payload type.</typeparam> /// <returns> /// A type that is defined to be a subtype of BinaryPipe<<typeparamref name="TKey"/>,<typeparamref name="TPayload"/>, <typeparamref name="TPayload"/>, <typeparamref name="TKey"/>, <typeparamref name="TPayload"/>>. /// </returns> internal static Tuple <Type, string> GenerateUnionPipeClass <TKey, TPayload>( UnionStreamable <TKey, TPayload> stream) { Contract.Requires(stream != null); Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(BinaryPipe <TKey, TPayload, TPayload, TPayload>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1)); #if CODEGEN_TIMING Stopwatch sw = new Stopwatch(); sw.Start(); #endif var template = new UnionTemplate($"GeneratedUnion_{UnionSequenceNumber++}", typeof(TKey), typeof(TPayload)); var gps = template.tm.GenericTypeVariables(template.keyType, template.resultType); template.genericParameters = gps.BracketedCommaSeparatedString(); var resultRepresentation = new ColumnarRepresentation(template.resultType); var batchGeneratedFrom_TKey_TPayload = Transformer.GetBatchClassName(template.keyType, template.resultType); var keyAndPayloadGenericParameters = template.tm.GenericTypeVariables(template.keyType, template.resultType).BracketedCommaSeparatedString(); template.GeneratedBatchName = batchGeneratedFrom_TKey_TPayload + keyAndPayloadGenericParameters; template.fields = resultRepresentation.AllFields; return(template.Generate <TKey, TPayload>()); }
private BinaryPipe <TKey, TPayload, TPayload, TPayload> GetPipe(IStreamObserver <TKey, TPayload> observer) { var lookupKey = CacheKey.Create(); var generatedPipeType = cachedPipes.GetOrAdd(lookupKey, key => UnionTemplate.GenerateUnionPipeClass(this)); Func <PlanNode, PlanNode, IBinaryObserver, BinaryPlanNode> planNode = ((PlanNode left, PlanNode right, IBinaryObserver o) => { var node = new UnionPlanNode( left, right, o, typeof(TKey), typeof(TPayload), false, true, this.ErrorMessages); return(node); }); var instance = Activator.CreateInstance(generatedPipeType.Item1, this, observer, planNode); var returnValue = (BinaryPipe <TKey, TPayload, TPayload, TPayload>)instance; return(returnValue); }
/// <summary> /// Generate a batch class definition to be used as a Union pipe. /// Compile the definition, dynamically load the assembly containing it, and return the Type representing the /// union pipe class. /// </summary> /// <typeparam name="TKey">The key type for both sides.</typeparam> /// <typeparam name="TPayload">The payload type.</typeparam> /// <returns> /// A type that is defined to be a subtype of BinaryPipe<<typeparamref name="TKey"/>,<typeparamref name="TPayload"/>, <typeparamref name="TPayload"/>, <typeparamref name="TKey"/>, <typeparamref name="TPayload"/>>. /// </returns> internal static Tuple <Type, string> GenerateUnionPipeClass <TKey, TPayload>( UnionStreamable <TKey, TPayload> stream) { Contract.Requires(stream != null); Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(BinaryPipe <TKey, TPayload, TPayload, TPayload>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1)); #if CODEGEN_TIMING Stopwatch sw = new Stopwatch(); sw.Start(); #endif string errorMessages = null; try { var template = new UnionTemplate(); var keyType = template.keyType = typeof(TKey); var payloadType = template.payloadType = typeof(TPayload); var tm = new TypeMapper(keyType, payloadType); template.TKey = tm.CSharpNameFor(keyType); template.TPayload = tm.CSharpNameFor(payloadType); var gps = tm.GenericTypeVariables(keyType, payloadType); template.genericParameters = gps.BracketedCommaSeparatedString(); template.className = string.Format("GeneratedUnion_{0}", UnionSequenceNumber++); var resultRepresentation = new ColumnarRepresentation(payloadType); var batchGeneratedFrom_TKey_TPayload = Transformer.GetBatchClassName(keyType, payloadType); var keyAndPayloadGenericParameters = tm.GenericTypeVariables(keyType, payloadType).BracketedCommaSeparatedString(); template.GeneratedBatchName = batchGeneratedFrom_TKey_TPayload + keyAndPayloadGenericParameters; template.fields = resultRepresentation.AllFields; template.staticCtor = Transformer.StaticCtor(template.className); var expandedCode = template.TransformText(); var assemblyReferences = Transformer.AssemblyReferencesNeededFor(typeof(TKey), typeof(TPayload)); assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly); assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TPayload>()); var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages); var realClassName = template.className.AddNumberOfNecessaryGenericArguments(keyType, payloadType); var t = a.GetType(realClassName); if (t.GetTypeInfo().IsGenericType) { var list = keyType.GetAnonymousTypes(); list.AddRange(payloadType.GetAnonymousTypes()); return(Tuple.Create(t.MakeGenericType(list.ToArray()), errorMessages)); } else { return(Tuple.Create(t, errorMessages)); } } catch { if (Config.CodegenOptions.DontFallBackToRowBasedExecution) { throw new InvalidOperationException("Code Generation failed when it wasn't supposed to!"); } return(Tuple.Create((Type)null, errorMessages)); } }