예제 #1
0
        public StandaloneMetric(SerialMetric metric)
        {
            if (metric == null)
            {
                throw new ArgumentNullException("metric");
            }

            _metric = metric;

            MetricAttribute attribute = _metric.GetType().GetCustomAttribute <MetricAttribute>();

            _fieldNames = attribute.NameToFieldIndexMap
                          .OrderBy(kvp => kvp.Value)
                          .Select(kvp => kvp.Key)
                          .ToArray();

            _singleOutput   = _fieldNames.Length == 1;
            _acceptBarInput = _metric is SingleOutputBarInputSerialMetric || _metric is MultipleOutputBarInputSerialMetric;

            _sobiMetric = _metric as SingleOutputBarInputSerialMetric;
            _soriMetric = _metric as SingleOutputRawInputSerialMetric;
            _mobiMetric = _metric as MultipleOutputBarInputSerialMetric;
            _moriMetric = _metric as MultipleOutputRawInputSerialMetric;
        }
        static MetricEvaluationContext()
        {
            Assembly assembly = Assembly.GetExecutingAssembly();

            var metrics = assembly.GetTypes()
                          .Where(type => type.IsClass &&
                                 typeof(SerialMetric).IsAssignableFrom(type));

            foreach (var metric in metrics)
            {
                if (metric == typeof(SerialMetric) ||
                    metric == typeof(BarInputSerialMetric) ||
                    metric == typeof(RawInputSerialMetric) ||
                    metric == typeof(SingleOutputBarInputSerialMetric) ||
                    metric == typeof(MultipleOutputBarInputSerialMetric) ||
                    metric == typeof(SingleOutputRawInputSerialMetric) ||
                    metric == typeof(MultipleOutputRawInputSerialMetric))

                {
                    continue;
                }

                if (!typeof(SingleOutputBarInputSerialMetric).IsAssignableFrom(metric) &&
                    !typeof(SingleOutputRawInputSerialMetric).IsAssignableFrom(metric) &&
                    !typeof(MultipleOutputBarInputSerialMetric).IsAssignableFrom(metric) &&
                    !typeof(MultipleOutputRawInputSerialMetric).IsAssignableFrom(metric))
                {
                    throw new InvalidProgramException(
                              string.Format(
                                  "Metric {0} is not inherited from class {1}, {2}, {3}, or {4}",
                                  typeof(SingleOutputBarInputSerialMetric).Name,
                                  typeof(SingleOutputRawInputSerialMetric).Name,
                                  typeof(MultipleOutputBarInputSerialMetric).Name,
                                  typeof(MultipleOutputRawInputSerialMetric).Name));
                }

                MetricAttribute attribute = metric.GetCustomAttribute <MetricAttribute>();

                if (attribute == null)
                {
                    throw new InvalidProgramException(
                              string.Format(
                                  "Metric class {0} has not been associated with MetricAttribute",
                                  metric.Name));
                }

                // validate if metric's attribute consistent with metric class
                if (typeof(SingleOutputBarInputSerialMetric).IsAssignableFrom(metric) ||
                    typeof(SingleOutputRawInputSerialMetric).IsAssignableFrom(metric))
                {
                    if (attribute.NameToFieldIndexMap.Count != 1)
                    {
                        throw new InvalidProgramException(
                                  string.Format(
                                      "Metric class {0} should have only single output, but its attribute declared {1} outputs",
                                      metric.Name,
                                      attribute.NameToFieldIndexMap.Count));
                    }
                }
                else if (typeof(MultipleOutputBarInputSerialMetric).IsAssignableFrom(metric) ||
                         typeof(MultipleOutputRawInputSerialMetric).IsAssignableFrom(metric))
                {
                    if (attribute.NameToFieldIndexMap.Count <= 1)
                    {
                        throw new InvalidProgramException(
                                  string.Format(
                                      "Metric class {0} should have multiple output, but its attribute declared {1} output",
                                      metric.Name,
                                      attribute.NameToFieldIndexMap.Count));
                    }
                }
                else
                {
                    // should never be here because above code has checked metric is inherited
                    // from the expected base classes
                    throw new InvalidProgramException("Run to unexpected code");
                }

                // validate metric names
                foreach (var name in attribute.ShortNames)
                {
                    if (NameToMetricAttributeMap.ContainsKey(name))
                    {
                        throw new InvalidProgramException(
                                  string.Format(
                                      "Short name {0} has been defined for class {1}",
                                      name,
                                      NameToMetricMap[name].Name));
                    }

                    NameToMetricAttributeMap.Add(name, attribute);

                    NameToMetricMap.Add(name, metric);
                }
            }
        }
        private MetricExpression Parse()
        {
            // parse the first part, such as MA[20]
            StandaloneMetric metric = ParseMetric();

            if (metric == null)
            {
                return(null);
            }

            // parse the call operation part, such as (MA[20])
            MetricExpression callee = null;

            Token token = PeekNextToken();

            if (token != null && token.Type == TokenType.LeftParenthese)
            {
                GetNextToken();

                callee = Parse();

                if (callee == null || !Expect(TokenType.RightParenthese, out token))
                {
                    return(null);
                }
            }

            // parse the selection part, such as .DIF
            int fieldIndex = -1;

            token = PeekNextToken();
            if (token != null && token.Type == TokenType.Dot)
            {
                GetNextToken();

                if (!Expect(TokenType.Identifier, out token))
                {
                    return(null);
                }

                string field = token.Value;

                // verify if the selection name is part of metric definition
                Type            metricType = metric.Metric.GetType();
                MetricAttribute attribute  = metricType.GetCustomAttribute <MetricAttribute>();

                if (!attribute.NameToFieldIndexMap.ContainsKey(field))
                {
                    LastErrorMessage = string.Format("{0} is not a valid subfield of metric {1}", field, metricType.Name);
                    return(null);
                }

                fieldIndex = attribute.NameToFieldIndexMap[field];
            }

            MetricExpression retValue = metric;

            if (callee != null)
            {
                retValue = new CallOperator(metric, callee);
            }

            if (fieldIndex >= 0)
            {
                retValue = new SelectionOperator(retValue, fieldIndex);
            }

            return(retValue);
        }