예제 #1
0
 public LogicalChannelBinding(
     LogicalChannel logicalChannel,
     LogicalChannelBindingMethodDesc consumingBindingDesc,
     LogicalChannelBindingMethodDesc consumingSignalBindingDesc)
 {
     LogicalChannel             = logicalChannel;
     ConsumingBindingDesc       = consumingBindingDesc;
     ConsumingSignalBindingDesc = consumingSignalBindingDesc;
 }
예제 #2
0
        private static LogicalChannelBindingMethodDesc FindMatchingMethod(
            string operatorName,
            Type target,
            LogicalChannel channelDesc,
            bool isPunctuation)
        {
            if (isPunctuation) {
                foreach (var method in target.GetMethods()) {
                    if (method.Name.Equals("OnSignal")) {
                        return new LogicalChannelBindingMethodDesc(method, LogicalChannelBindingTypePassAlong.INSTANCE);
                    }
                }

                return null;
            }

            var outputPort = channelDesc.OutputPort;

            Type[] expectedIndividual;
            Type expectedUnderlying;
            EventType expectedUnderlyingType;
            var typeDesc = outputPort.GraphTypeDesc;

            if (typeDesc.IsWildcard) {
                expectedIndividual = new Type[0];
                expectedUnderlying = null;
                expectedUnderlyingType = null;
            }
            else {
                expectedIndividual = new Type[typeDesc.EventType.PropertyNames.Length];
                var i = 0;
                foreach (var descriptor in typeDesc.EventType.PropertyDescriptors) {
                    expectedIndividual[i] = descriptor.PropertyType;
                    i++;
                }

                expectedUnderlying = typeDesc.EventType.UnderlyingType;
                expectedUnderlyingType = typeDesc.EventType;
            }

            string channelSpecificMethodName = null;
            if (channelDesc.ConsumingOptStreamAliasName != null) {
                channelSpecificMethodName = "On" + channelDesc.ConsumingOptStreamAliasName;
            }
            
            var methods = target.GetMethods();
            foreach (var method in methods) {
                var eligible = method.Name.Equals("OnInput");
                if (!eligible && method.Name.Equals(channelSpecificMethodName)) {
                    eligible = true;
                }

                if (!eligible) {
                    continue;
                }

                // handle Object[]
                var paramTypes = method.GetParameterTypes();
                var numParams = paramTypes.Length;

                if (expectedUnderlying != null) {
                    if (numParams == 1 &&
                        TypeHelper.IsAssignmentCompatible(expectedUnderlying, paramTypes[0])) {
                        return new LogicalChannelBindingMethodDesc(
                            method, LogicalChannelBindingTypePassAlong.INSTANCE);
                    }

                    if (numParams == 2 &&
                        paramTypes[0].GetBoxedType() == typeof(int?) &&
                        TypeHelper.IsAssignmentCompatible(expectedUnderlying, paramTypes[1])) {
                        return new LogicalChannelBindingMethodDesc(
                            method,
                            new LogicalChannelBindingTypePassAlongWStream(channelDesc.ConsumingOpStreamNum));
                    }
                }

                if (numParams == 1 &&
                    (paramTypes[0] == typeof(object) ||
                     paramTypes[0] == typeof(object[]) &&
                     method.IsVarArgs())) {
                    return new LogicalChannelBindingMethodDesc(
                        method, LogicalChannelBindingTypePassAlong.INSTANCE);
                }

                if (numParams == 2 &&
                    paramTypes[0] == typeof(int) &&
                    (paramTypes[1] == typeof(object) ||
                     paramTypes[1] == typeof(object[]) &&
                     method.IsVarArgs())) {
                    return new LogicalChannelBindingMethodDesc(
                        method,
                        new LogicalChannelBindingTypePassAlongWStream(channelDesc.ConsumingOpStreamNum));
                }

                // if exposing a method that exactly matches each property type in order, use that, i.e. "onInut(String p0, int p1)"
                if (expectedUnderlyingType is ObjectArrayEventType &&
                    TypeHelper.IsSignatureCompatible(expectedIndividual, paramTypes)) {
                    return new LogicalChannelBindingMethodDesc(method, LogicalChannelBindingTypeUnwind.INSTANCE);
                }
            }

            ISet<string> choices = new LinkedHashSet<string>();
            choices.Add(typeof(object).Name);
            choices.Add("Object[]");
            if (expectedUnderlying != null) {
                choices.Add(expectedUnderlying.Name);
            }

            throw new ExprValidationException(
                "Failed to find OnInput method on for operator '" +
                operatorName +
                "' class " +
                target.Name +
                ", expected an OnInput method that takes any of {" +
                CollectionUtil.ToString(choices) +
                "}");
        }