Пример #1
0
        //============================================================================
        /// <summary>
        /// Recursive routine for checking whether two types are (a) identical,
        /// (b) different but compatible, (c) incompatible.
        /// <para>Note:</para>
        /// <para>1. Type compatibility is not a transitive relationship.</para>
        /// <para>2. Unit compatibility needs further implementation.</para>
        /// </summary>
        /// <param name="srcValue">The TTypedValue to compare with.</param>
        /// <returns>Returns: 0 - exact match, 1 - compatible, -1 - cannot match</returns>
        //============================================================================
        public int canAssignFrom(TTypedValue srcValue)
        {
            int result = ctBAD;
            uint Idx;

            if (srcValue.isScalar())
            {
                if (!FIsScalar)
                    result = ctBAD;
                else if (srcValue.baseType() == FBaseType)
                    result = ctSAME;
                else if ((srcValue.baseType() <= TBaseType.ITYPE_INT8) && (srcValue.baseType() >= TBaseType.ITYPE_INT1) &&
                         (FBaseType <= TBaseType.ITYPE_INT8) && (FBaseType >= TBaseType.ITYPE_INT1))
                    result = ctCOMP;  //both integers
                else if ((FBaseType >= TBaseType.ITYPE_SINGLE) && (FBaseType <= TBaseType.ITYPE_DOUBLE) &&           //These conditions are not transitive
                         (srcValue.baseType() >= TBaseType.ITYPE_INT1) && (srcValue.baseType() <= TBaseType.ITYPE_DOUBLE))
                    result = ctCOMP;  //can match an int/single source to single/double destination
                else if ((srcValue.baseType() == TBaseType.ITYPE_CHAR) &&
                    ((FBaseType == TBaseType.ITYPE_WCHAR) ||
                    (FBaseType == TBaseType.ITYPE_STR) ||
                    (FBaseType == TBaseType.ITYPE_WSTR)))
                    result = ctCOMP;
                else if ((srcValue.baseType() == TBaseType.ITYPE_WCHAR) && (FBaseType == TBaseType.ITYPE_WSTR))
                    result = ctCOMP;
                else if ((srcValue.baseType() == TBaseType.ITYPE_STR) && (FBaseType == TBaseType.ITYPE_WSTR))
                    result = ctCOMP;
                // A sop to the old APSIM manager, which sends out all request-set values as strings
                else if ((srcValue.baseType() == TBaseType.ITYPE_STR) || (FBaseType == TBaseType.ITYPE_WSTR))
                    result = ctDODGY;
                else
                    result = ctBAD;

                if ((FBaseType >= TBaseType.ITYPE_INT1) && (FBaseType <= TBaseType.ITYPE_DOUBLE) &&
                      (!unitsMatch(units(), srcValue.units())))
                    result = ctBAD;
            }
            else if (srcValue.isArray())
            {   //an array
                if (!FIsArray)
                    result = ctBAD;
                else
                {
                    if (count() == 0)
                        setElementCount(1);  //addElement();
                    if (srcValue.count() == 0)
                        srcValue.setElementCount(1); //addElement();
                    result = member(1).canAssignFrom(srcValue.member(1));
                }
            }
            else
            {   //a record
                if (!isRecord())
                    result = ctBAD;
                else
                {
                    uint iCount = count();
                    result = ctCOMP;                                                        // First, test for identity
                    if (iCount == srcValue.count())
                    {
                        result = ctSAME;
                        for (Idx = 1; Idx <= iCount; Idx++)
                        {
                            if ((member(Idx).Name.ToLower() != srcValue.member(Idx).Name.ToLower()) ||
                                  (member(Idx).canAssignFrom(srcValue.member(Idx)) != ctSAME))
                                result = ctCOMP;
                        }
                    }

                    if (result == ctCOMP)
                    {                                                //If not same, test for compatibility
                        String elemName;
                        for (Idx = 1; Idx <= srcValue.count(); Idx++)
                        {
                            elemName = srcValue.member(Idx).Name;                 //field name
                            if (!hasField(elemName) ||
                                  (member(elemName).canAssignFrom(srcValue.member(Idx)) == ctBAD))
                                result = ctBAD;
                        }
                    }
                }
            }

            return result;
        }