Exemplo n.º 1
0
        /// <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&lt;<typeparamref name="TKey"/>,<typeparamref name="TPayload"/>, <typeparamref name="TPayload"/>, <typeparamref name="TKey"/>, <typeparamref name="TPayload"/>&gt;.
        /// </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>());
        }
Exemplo n.º 2
0
        /// <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&lt;<typeparamref name="TKey"/>,<typeparamref name="TPayload"/>, <typeparamref name="TPayload"/>, <typeparamref name="TKey"/>, <typeparamref name="TPayload"/>&gt;.
        /// </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));
            }
        }