/// <summary> /// Generate a batch class definition to be used as a Beat pipe. /// Compile the definition, dynamically load the assembly containing it, and return the Type representing the /// Beat 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 UnaryPipe<<typeparamref name="TKey"/>,<typeparamref name="TPayload"/>, <typeparamref name="TPayload"/>>. /// </returns> internal static Tuple <Type, string> Generate <TKey, TPayload>(BeatStreamable <TKey, TPayload> stream) { Contract.Requires(stream != null); Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(UnaryPipe <TKey, TPayload, TPayload>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1)); #if CODEGEN_TIMING Stopwatch sw = new Stopwatch(); sw.Start(); #endif var template = new BeatTemplate( string.Format("GeneratedBeat_{0}", BeatSequenceNumber++), typeof(TKey), typeof(TPayload)); template.ActiveEventType = typeof(TPayload).GetTypeInfo().IsValueType ? template.TPayload : "Active_Event"; #region Key Comparer var keyComparer = stream.Properties.KeyEqualityComparer.GetEqualsExpr(); template.keyComparer = (left, right) => keyComparer.Inline(left, right); #endregion #region Payload Comparer var payloadComparer = stream.Properties.PayloadEqualityComparer.GetEqualsExpr(); var newLambda = Extensions.TransformFunction <TKey, TPayload>(payloadComparer, "index"); template.payloadComparer = (left, right) => newLambda.Inline(left, right); #endregion return(template.Generate <TKey, TPayload>(typeof(IStreamable <,>))); }
private UnaryPipe <TKey, TPayload, TPayload> GetPipe(IStreamObserver <TKey, TPayload> observer) { var lookupKey = CacheKey.Create(this.Properties.KeyEqualityComparer.GetEqualsExpr().ExpressionToCSharp(), this.Properties.PayloadEqualityComparer.GetEqualsExpr().ExpressionToCSharp()); var generatedPipeType = cachedPipes.GetOrAdd(lookupKey, key => BeatTemplate.Generate(this)); Func <PlanNode, IQueryObject, PlanNode> planNode = ((PlanNode p, IQueryObject o) => new BeatPlanNode(p, o, typeof(TKey), typeof(TPayload), this.Offset, this.Period, true, generatedPipeType.Item2)); var instance = Activator.CreateInstance(generatedPipeType.Item1, this, observer, planNode, this.Offset, this.Period); var returnValue = (UnaryPipe <TKey, TPayload, TPayload>)instance; return(returnValue); }
protected override bool CanGenerateColumnar() { var typeOfTKey = typeof(TKey); if (typeOfTKey.GetPartitionType() != null) { return(false); } // This operator can handle a pseudo-columnar payload type, e.g., string. var lookupKey = CacheKey.Create(this.Properties.KeyEqualityComparer.GetEqualsExpr().ExpressionToCSharp(), this.Properties.PayloadEqualityComparer.GetEqualsExpr().ExpressionToCSharp()); var generatedPipeType = cachedPipes.GetOrAdd(lookupKey, key => BeatTemplate.Generate(this)); this.errorMessages = generatedPipeType.Item2; return(generatedPipeType.Item1 != null); }