public static Type FindInputPortDataType(this ComponentConfiguration config, IPortMetadata portMetadata, IReadOnlyList <ComponentConfiguration> configs, params Tuple <ComponentConfiguration, IPortMetadata>[] exclude)
        {
            var dataType = portMetadata.GetTransmissionDataType(null, Array.Empty <Type>(), Array.Empty <Type>());

            if (dataType is null)
            {
                var i = config.Inputs.FirstOrDefault(c => Equals(c.LocalPort.Identifier, portMetadata.Identifier));
                if (i is null)
                {
                    return(null);
                }
                foreach (var other in configs)
                {
                    if (Equals(i.RemoteId, other.Id))
                    {
                        var newExclude = new Tuple <ComponentConfiguration, IPortMetadata> [exclude.Length + 1];
                        Array.Copy(exclude, newExclude, exclude.Length);
                        var oMetadata = other.FindPortMetadata(i.RemotePort);
                        newExclude[exclude.Length] = new Tuple <ComponentConfiguration, IPortMetadata>(other, oMetadata);
                        var otherInput  = FindInputPortDataTypes(other, configs, newExclude);
                        var otherOutput = FindOutputPortDataTypes(other, configs, newExclude);
                        var otherEnd    = oMetadata.GetTransmissionDataType(null, otherInput, otherOutput);
                        if (otherEnd != null)
                        {
                            dataType = portMetadata.GetTransmissionDataType(otherEnd, Array.Empty <Type>(), Array.Empty <Type>());
                            if (dataType != null)
                            {
                                goto jump;
                            }
                            newExclude[exclude.Length] = new Tuple <ComponentConfiguration, IPortMetadata>(config, portMetadata);
                            var selfOutput = FindOutputPortDataTypes(config, configs, newExclude);
                            dataType = portMetadata.GetTransmissionDataType(otherEnd, selfOutput, Array.Empty <Type>());
                            if (dataType != null)
                            {
                                goto jump;
                            }
                            var selfInput = FindInputPortDataTypes(config, configs, newExclude);
                            dataType = portMetadata.GetTransmissionDataType(otherEnd, selfOutput, selfInput);
                            if (dataType != null)
                            {
                                goto jump;
                            }
                        }
                    }
                }
                jump :;
            }
            return(dataType);
        }
        public static IList <Type> FindOutputPortDataTypes(this ComponentConfiguration config, IReadOnlyList <ComponentConfiguration> configs, params Tuple <ComponentConfiguration, IPortMetadata>[] exclude)
        {
            var outputPorts = config.GetMetadata().OutputPorts().ToArray();
            var result      = new Type[outputPorts.Length];
            var idx         = 0;

            foreach (var oMetadata in outputPorts)
            {
                Type dataType;
                if (exclude != null && exclude.Any(ex => ex.Item1.Id == config.Id && Equals(ex.Item2.Identifier, oMetadata.Identifier)))
                {
                    dataType = null;
                }
                else
                {
                    dataType = FindOutputPortDataType(config, oMetadata, configs, exclude);
                }
                result[idx] = dataType;
                idx++;
            }
            return(result);
        }
        /// <summary>
        /// Requirement: all local input metadata should be StaticPortMetadata, and all remote output connectors should be IProducer<T>
        /// </summary>
        /// <param name="componentConfiguration"></param>
        /// <param name="instance"></param>
        /// <param name="instantiatedComponents"></param>
        public static void ConnectAllStaticInputs(this ComponentConfiguration componentConfiguration, object instance, IReadOnlyList <ComponentEnvironment> instantiatedComponents)
        {
            foreach (var inputConfig in componentConfiguration.Inputs)
            {
                var inputMetadata = componentConfiguration.FindPortMetadata(inputConfig.LocalPort);
                Debug.Assert(inputMetadata.Direction == PortDirection.Input);
                var inputStaticMetadata = inputMetadata as StaticPortMetadata;
                if (inputStaticMetadata is null)
                {
                    continue;
                }
                var     dataType        = inputStaticMetadata.DataType;
                var     getConsumerFunc = typeof(HelperExtensions).GetMethod(nameof(GetStaticConsumer)).MakeGenericMethod(dataType);
                dynamic consumer        = getConsumerFunc.Invoke(null, new object[] { inputStaticMetadata, inputConfig.LocalPort, instance });

                var remoteEnvironment    = instantiatedComponents.Single(e => inputConfig.RemoteId == e.Configuration.Id);
                var remoteOutputMetadata = remoteEnvironment.FindPortMetadata(inputConfig.RemotePort);
                Debug.Assert(remoteOutputMetadata.Direction == PortDirection.Output);
                var     getProducerFunc = typeof(HelperExtensions).GetMethod(nameof(GetProducer)).MakeGenericMethod(dataType);
                dynamic producer        = getProducerFunc.Invoke(null, new object[] { remoteEnvironment, inputConfig.RemotePort });

                Operators.PipeTo(producer, consumer, inputConfig.DeliveryPolicy);
            }
        }
 public static IList <Type> FindOutputPortDataTypes(this ComponentConfiguration config, IReadOnlyList <ComponentConfiguration> configs, IPortMetadata exclude)
 {
     return(FindOutputPortDataTypes(config, configs, new Tuple <ComponentConfiguration, IPortMetadata>(config, exclude)));
 }
 public static IPortMetadata FindPortMetadata(this ComponentConfiguration componentConfiguration, PortConfiguration port)
 {
     return(componentConfiguration.GetMetadata().FindPortMetadata(port));
 }