private void MakeUnderlyingCodegen(
            CodegenMethodScope method,
            CodegenBlock block,
            CodegenClassScope codegenClassScope)
        {
            block
                .DeclareVar(
                    _beanEventType.UnderlyingType,
                    "und",
                    Cast(_beanEventType.UnderlyingType, _beanInstantiator.Make(method, codegenClassScope)))
                .DeclareVar<object>("value", ConstantNull());

            for (var i = 0; i < _writeMembersReflection.Length; i++) {
                block.AssignRef("value", ArrayAtIndex(Ref("properties"), Constant(i)));

                Type targetType;

                var writeMember = _writeMembersReflection[i];
                if (writeMember is MethodInfo writeMethod) {
                    targetType = writeMethod.GetParameters()[0].ParameterType;
                }
                else if (writeMember is PropertyInfo writeProperty) {
                    targetType = writeProperty.PropertyType;
                }
                else {
                    throw new IllegalStateException("writeMember of invalid type");
                }

                CodegenExpression value;
                //if (targetType.IsValueType) {
                //    var caster = SimpleTypeCasterFactory.GetCaster(typeof(object), targetType);
                //    value = caster.Codegen(Ref("value"), typeof(object), method, codegenClassScope);
                //}
                //else {

                var caster = SimpleTypeCasterFactory.GetCaster(typeof(object), targetType);
                value = caster.Codegen(Ref("value"), typeof(object), method, codegenClassScope);

                //}

                CodegenExpression set = null;

                if (writeMember is MethodInfo) {
                    set = ExprDotMethod(Ref("und"), writeMember.Name, value);
                }
                else if (writeMember is PropertyInfo) {
                    set = SetProperty(Ref("und"), writeMember.Name, value);
                }

                if (_primitiveType[i]) {
                    block.IfRefNotNull("value").Expression(set).BlockEnd();
                }
                else {
                    block.Expression(set);
                }
            }

            block.ReturnMethodOrBlock(Ref("und"));
        }
Ejemplo n.º 2
0
        private void MakeUnderlyingCodegen(
            CodegenBlock block,
            CodegenMethodScope method,
            CodegenClassScope codegenClassScope)
        {
            block
            .DeclareVar(_jsonEventType.UnderlyingType, "und", Cast(_jsonEventType.UnderlyingType, _beanInstantiator.Make(method, codegenClassScope)))
            .DeclareVar <object>("value", ConstantNull());

            for (var i = 0; i < _writeFieldReflection.Length; i++)
            {
                block.AssignRef("value", ArrayAtIndex(Ref("properties"), Constant(i)));

                var targetType = _writeFieldReflection[i].FieldType;
                CodegenExpression value;
                if (targetType.IsPrimitive)
                {
                    var caster = SimpleTypeCasterFactory.GetCaster(typeof(object), targetType);
                    value = caster.Codegen(Ref("value"), typeof(object), method, codegenClassScope);
                }
                else
                {
                    value = Cast(targetType, Ref("value"));
                }

                var set = Assign(ExprDotName(Ref("und"), _writeFieldReflection[i].Name), value);
                if (_primitiveType[i])
                {
                    block.IfRefNotNull("value").Expression(set).BlockEnd();
                }
                else
                {
                    block.Expression(set);
                }
            }

            block.BlockReturn(Ref("und"));
        }
Ejemplo n.º 3
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            if (ChildNodes.Count == 0 || ChildNodes.Count > 2)
            {
                throw new ExprValidationException("Cast function node must have one or two child expressions");
            }

            var valueEvaluator = ChildNodes[0].ExprEvaluator;
            var fromType       = valueEvaluator.ReturnType;

            // determine date format parameter
            var namedParams =
                ExprNodeUtility.GetNamedExpressionsHandleDups(ChildNodes);

            ExprNodeUtility.ValidateNamed(namedParams, new string[] { "dateformat" });
            var dateFormatParameter = namedParams.Get("dateformat");

            if (dateFormatParameter != null)
            {
                ExprNodeUtility.ValidateNamedExpectType(
                    dateFormatParameter, new Type[] { typeof(string) });
            }

            // identify target type
            // try the primitive names including "string"
            _targetType = TypeHelper.GetPrimitiveTypeForName(_classIdentifier.Trim()).GetBoxedType();

            SimpleTypeCaster     caster;
            bool                 numeric;
            CasterParserComputer casterParserComputer = null;

            var classIdentifierInvariant = _classIdentifier.Trim().ToLowerInvariant();

            if (dateFormatParameter != null)
            {
                if (fromType != typeof(string))
                {
                    throw new ExprValidationException(
                              string.Format("Use of the '{0}' named parameter requires a string-type input", dateFormatParameter.ParameterName));
                }

                if (_targetType == null)
                {
                    try
                    {
                        _targetType = TypeHelper.GetClassForName(
                            _classIdentifier.Trim(), validationContext.EngineImportService.GetClassForNameProvider());
                    }
                    catch (TypeLoadException)
                    {
                        // expected
                    }
                }

                // dynamic or static date format
                numeric = false;
                caster  = null;


                StringToDateTimeBaseComputer dateTimeComputer;

                if (_targetType == typeof(DateTime) ||
                    _targetType == typeof(DateTime?) ||
                    classIdentifierInvariant.Equals("date"))
                {
                    _targetType = typeof(DateTime);

                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.StaticDateFormat != null)
                    {
                        if (desc.Iso8601Format)
                        {
                            dateTimeComputer = new StringToDateTimeWStaticISOFormatComputer(validationContext.EngineImportService.TimeZone);
                            dateTimeComputer.HandleParseException += HandleParseISOException;
                        }
                        else
                        {
                            dateTimeComputer = new StringToDateTimeWStaticFormatComputer(desc.StaticDateFormat);
                            dateTimeComputer.HandleParseException += HandleParseException;
                        }
                    }
                    else
                    {
                        dateTimeComputer = new StringToDateTimeWDynamicFormatComputer(desc.DynamicDateFormat);
                        dateTimeComputer.HandleParseException += HandleParseException;
                    }
                }
                else if (_targetType == typeof(DateTimeOffset) ||
                         _targetType == typeof(DateTimeOffset?) ||
                         classIdentifierInvariant.Equals("dto") ||
                         classIdentifierInvariant.Equals("datetimeoffset"))
                {
                    _targetType = typeof(DateTimeOffset);

                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.StaticDateFormat != null)
                    {
                        if (desc.Iso8601Format)
                        {
                            dateTimeComputer = new StringToDtoWStaticISOFormatComputer(validationContext.EngineImportService.TimeZone);
                            dateTimeComputer.HandleParseException += HandleParseISOException;
                        }
                        else
                        {
                            dateTimeComputer = new StringToDtoWStaticFormatComputer(desc.StaticDateFormat, validationContext.EngineImportService.TimeZone);
                            dateTimeComputer.HandleParseException += HandleParseException;
                        }
                    }
                    else
                    {
                        dateTimeComputer = new StringToDtoWDynamicFormatComputer(desc.DynamicDateFormat, validationContext.EngineImportService.TimeZone);
                        dateTimeComputer.HandleParseException += HandleParseException;
                    }
                }
                else if (_targetType == typeof(DateTimeEx) ||
                         classIdentifierInvariant.Equals("dtx") ||
                         classIdentifierInvariant.Equals("datetimeex") ||
                         classIdentifierInvariant.Equals("calendar"))
                {
                    _targetType = typeof(DateTimeEx);

                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.StaticDateFormat != null)
                    {
                        if (desc.Iso8601Format)
                        {
                            dateTimeComputer = new StringToDtxWStaticISOFormatComputer(validationContext.EngineImportService.TimeZone);
                            dateTimeComputer.HandleParseException += HandleParseISOException;
                        }
                        else
                        {
                            dateTimeComputer = new StringToDtxWStaticFormatComputer(desc.StaticDateFormat, validationContext.EngineImportService.TimeZone);
                            dateTimeComputer.HandleParseException += HandleParseException;
                        }
                    }
                    else
                    {
                        dateTimeComputer = new StringToDtxWDynamicFormatComputer(desc.DynamicDateFormat, validationContext.EngineImportService.TimeZone);
                        dateTimeComputer.HandleParseException += HandleParseException;
                    }
                }
                else if (_targetType == typeof(long) || _targetType == typeof(long?))
                {
                    _targetType = typeof(long);

                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.StaticDateFormat != null)
                    {
                        if (desc.Iso8601Format)
                        {
                            dateTimeComputer = new StringToDateTimeLongWStaticISOFormatComputer(validationContext.EngineImportService.TimeZone);
                            dateTimeComputer.HandleParseException += HandleParseISOException;
                        }
                        else
                        {
                            dateTimeComputer = new StringToDateTimeLongWStaticFormatComputer(desc.StaticDateFormat);
                            dateTimeComputer.HandleParseException += HandleParseException;
                        }
                    }
                    else
                    {
                        dateTimeComputer = new StringToDateTimeLongWDynamicFormatComputer(desc.DynamicDateFormat);
                        dateTimeComputer.HandleParseException += HandleParseException;
                    }
                }
                else
                {
                    throw new ExprValidationException(
                              "Use of the '" + dateFormatParameter.ParameterName +
                              "' named parameter requires a target type of long or datetime");
                }

                casterParserComputer = dateTimeComputer;
            }
            else if (_targetType != null)
            {
                _targetType = _targetType.GetBoxedType();
                caster      = SimpleTypeCasterFactory.GetCaster(fromType, _targetType);
                numeric     = _targetType.IsNumeric();
            }
            else if (String.Equals(classIdentifierInvariant, "bigint", StringComparison.InvariantCultureIgnoreCase) ||
                     String.Equals(classIdentifierInvariant, "biginteger", StringComparison.InvariantCultureIgnoreCase))
            {
                _targetType = typeof(BigInteger);
                caster      = SimpleTypeCasterFactory.GetCaster(fromType, _targetType);
                numeric     = true;
            }
            else if (classIdentifierInvariant.Equals("decimal".ToLowerInvariant()))
            {
                _targetType = typeof(decimal);
                caster      = SimpleTypeCasterFactory.GetCaster(fromType, _targetType);
                numeric     = true;
            }
            else
            {
                try
                {
                    _targetType = TypeHelper.GetClassForName(
                        _classIdentifier.Trim(), validationContext.EngineImportService.GetClassForNameProvider());
                }
                catch (TypeLoadException e)
                {
                    throw new ExprValidationException(
                              "Type as listed in cast function by name '" + _classIdentifier + "' cannot be loaded", e);
                }
                numeric = _targetType.IsNumeric();
                caster  = numeric
                    ? SimpleTypeCasterFactory.GetCaster(fromType, _targetType)
                    : SimpleTypeCasterFactory.GetCaster(_targetType);
            }

            // assign a computer unless already assigned
            if (casterParserComputer == null)
            {
                // to-string
                if (_targetType == typeof(string))
                {
                    casterParserComputer = new StringXFormComputer();
                }
                else if (fromType == typeof(string))
                {
                    // parse
                    var parser = SimpleTypeParserFactory.GetParser(_targetType.GetBoxedType());
                    casterParserComputer = new StringParserComputer(parser);
                }
                else if (numeric)
                {
                    // numeric cast with check
                    casterParserComputer = new NumericCasterComputer(caster);
                }
                else
                {
                    // non-numeric cast
                    casterParserComputer = new NonnumericCasterComputer(caster);
                }
            }

            // determine constant or not
            Object theConstant = null;

            if (ChildNodes[0].IsConstantResult)
            {
                _isConstant = casterParserComputer.IsConstantForConstInput;
                if (_isConstant)
                {
                    var evaluateParams = new EvaluateParams(null, true, validationContext.ExprEvaluatorContext);
                    var @in            = valueEvaluator.Evaluate(evaluateParams);
                    theConstant = @in == null ? null : casterParserComputer.Compute(@in, evaluateParams);
                }
            }

            // determine evaluator
            if (_isConstant)
            {
                _exprEvaluator = new ExprCastNodeConstEval(this, theConstant);
            }
            else
            {
                _exprEvaluator = new ExprCastNodeNonConstEval(this, valueEvaluator, casterParserComputer);
            }
            return(null);
        }
        public VariantPropertyDesc ResolveProperty(String propertyName, EventType[] variants)
        {
            bool existsInAll = true;
            Type commonType  = null;
            bool mustCoerce  = false;

            for (int i = 0; i < variants.Length; i++)
            {
                Type type = variants[i].GetPropertyType(propertyName); //.GetBoxedType();
                if (type == null)
                {
                    existsInAll = false;
                    continue;
                }

                if (commonType == null)
                {
                    commonType = type;
                    continue;
                }

                // compare types
                if (type == commonType)
                {
                    continue;
                }

                if (type.GetBoxedType() == commonType.GetBoxedType())
                {
                    commonType = commonType.GetBoxedType();
                    continue;
                }

                // coercion
                if (type.IsNumeric())
                {
                    if (TypeHelper.CanCoerce(type, commonType))
                    {
                        mustCoerce = true;
                        continue;
                    }
                    if (TypeHelper.CanCoerce(commonType, type))
                    {
                        mustCoerce = true;
                        commonType = type;
                    }
                }
                else if (commonType == typeof(Object))
                {
                    continue;
                }
                // common interface or base class
                else if (!type.IsBuiltinDataType())
                {
                    var supersForType = new FIFOHashSet <Type>();
                    TypeHelper.GetBase(type, supersForType);
                    supersForType.Remove(typeof(Object));

                    if (supersForType.Contains(commonType))
                    {
                        continue;   // type, or : common type
                    }
                    if (TypeHelper.IsSubclassOrImplementsInterface(commonType, type))
                    {
                        commonType = type;  // common type : type
                        continue;
                    }

                    // find common interface or type both implement
                    var supersForCommonType = new FIFOHashSet <Type>();
                    TypeHelper.GetBase(commonType, supersForCommonType);
                    supersForCommonType.Remove(typeof(Object));

                    // Take common classes first, ignoring interfaces
                    bool found = false;
                    foreach (Type superClassType in supersForType)
                    {
                        if (!superClassType.IsInterface && (supersForCommonType.Contains(superClassType)))
                        {
                            break;
                        }
                    }
                    if (found)
                    {
                        continue;
                    }
                    // Take common interfaces
                    foreach (var superClassType in supersForType)
                    {
                        if (superClassType.IsInterface && supersForCommonType.Contains(superClassType))
                        {
                            commonType = superClassType;
                            found      = true;
                            break;
                        }
                    }
                }

                commonType = typeof(Object);
            }

            if (!existsInAll)
            {
                return(null);
            }

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

            // property numbers should start at zero since the serve as array index
            var assignedPropertyNumber = currentPropertyNumber;

            currentPropertyNumber++;
            propertyGetterCache.AddGetters(assignedPropertyNumber, propertyName);

            EventPropertyGetter getter;

            if (mustCoerce)
            {
                SimpleTypeCaster caster = SimpleTypeCasterFactory.GetCaster(null, commonType);
                getter = new ProxyEventPropertyGetter
                {
                    ProcGet = eventBean =>
                    {
                        var variant        = (VariantEvent)eventBean;
                        var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType);
                        if (propertyGetter == null)
                        {
                            return(null);
                        }
                        var value = propertyGetter.Get(variant.UnderlyingEventBean);
                        if (value == null)
                        {
                            return(value);
                        }
                        return(caster.Invoke(value));
                    },
                    ProcGetFragment      = eventBean => null,
                    ProcIsExistsProperty = eventBean =>
                    {
                        var variant        = (VariantEvent)eventBean;
                        var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType);
                        if (propertyGetter == null)
                        {
                            return(false);
                        }
                        return(propertyGetter.IsExistsProperty(variant.UnderlyingEventBean));
                    }
                };
            }
            else
            {
                getter = new ProxyEventPropertyGetter
                {
                    ProcGet = eventBean =>
                    {
                        var variant        = (VariantEvent)eventBean;
                        var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType);
                        if (propertyGetter == null)
                        {
                            return(null);
                        }
                        return(propertyGetter.Get(variant.UnderlyingEventBean));
                    },
                    ProcGetFragment      = eventBean => null,
                    ProcIsExistsProperty = eventBean =>
                    {
                        var variant        = (VariantEvent)eventBean;
                        var propertyGetter = propertyGetterCache.GetGetter(assignedPropertyNumber, variant.UnderlyingEventBean.EventType);
                        if (propertyGetter == null)
                        {
                            return(false);
                        }
                        return(propertyGetter.IsExistsProperty(variant.UnderlyingEventBean));
                    }
                };
            }

            return(new VariantPropertyDesc(commonType, getter, true));
        }
Ejemplo n.º 5
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            if (ChildNodes.Length == 0 || ChildNodes.Length > 2) {
                throw new ExprValidationException("Cast function node must have one or two child expressions");
            }

            var fromType = ChildNodes[0].Forge.EvaluationType;
            var classIdentifier = ClassIdentifierWArray.ClassIdentifier;
            var classIdentifierInvariant = classIdentifier.Trim();
            var arrayDimensions = ClassIdentifierWArray.ArrayDimensions;

            // Local function to match a class identifier
            bool MatchesClassIdentifier(string identifier)
            {
                return string.Equals(
                    classIdentifierInvariant,
                    identifier,
                    StringComparison.InvariantCultureIgnoreCase);
            }
            
            // determine date format parameter
            var namedParams =
                ExprNodeUtilityValidate.GetNamedExpressionsHandleDups(ChildNodes);
            ExprNodeUtilityValidate.ValidateNamed(namedParams, new[] {"dateformat"});
            var dateFormatParameter = namedParams.Get("dateformat");
            if (dateFormatParameter != null) {
                ExprNodeUtilityValidate.ValidateNamedExpectType(
                    dateFormatParameter,
                    new[] {
                        typeof(string), 
                        typeof(DateFormat), 
                        typeof(DateTimeFormat)
                    });
            }

            // identify target type
            // try the primitive names including "string"
            SimpleTypeCaster caster;
            var targetType = TypeHelper.GetPrimitiveTypeForName(classIdentifier.Trim());
            if (!ClassIdentifierWArray.IsArrayOfPrimitive) {
                targetType = targetType.GetBoxedType();
            }

            targetType = ApplyDimensions(targetType);

            bool numeric;
            CasterParserComputerForge casterParserComputerForge = null;
            if (dateFormatParameter != null) {
                if (fromType != typeof(string)) {
                    throw new ExprValidationException(
                        "Use of the '" +
                        dateFormatParameter.ParameterName +
                        "' named parameter requires a string-type input");
                }

                if (targetType == null) {
                    try {
                        targetType = TypeHelper.GetClassForName(
                            classIdentifier.Trim(),
                            validationContext.ImportService.ClassForNameProvider);
                        targetType = ApplyDimensions(targetType);
                    }
                    catch (TypeLoadException) {
                        // expected
                    }
                }

                // dynamic or static date format
                numeric = false;
                caster = null;

                if (targetType == typeof(DateTimeEx) ||
                    MatchesClassIdentifier("calendar") ||
                    MatchesClassIdentifier("dateTimeEx")) {
                    targetType = typeof(DateTimeEx);

                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.IsIso8601Format) {
                        casterParserComputerForge = new StringToDateTimeExIsoFormatComputer();
                    }
                    else if (desc.StaticDateFormat != null) {
                        casterParserComputerForge = new StringToDateTimExWStaticFormatComputer(
                            desc.StaticDateFormat,
                            TimeZoneInfo.Utc); // Note how code-generation does not use the default time zone
                    }
                    else {
                        casterParserComputerForge = new StringToDateTimeExWExprFormatComputer(
                            desc.DynamicDateFormat,
                            TimeZoneInfo.Utc);
                    }
                }
                else if (targetType == typeof(DateTimeOffset) ||
                         targetType == typeof(DateTimeOffset?) ||
                         MatchesClassIdentifier("dto") ||
                         MatchesClassIdentifier("datetimeoffset")) {
                    targetType = typeof(DateTimeOffset);
                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.IsIso8601Format) {
                        casterParserComputerForge = new StringToDateTimeOffsetIsoFormatComputer();
                    }
                    else if (desc.StaticDateFormat != null) {
                        casterParserComputerForge =
                            new StringToDateTimeOffsetWStaticFormatComputer(desc.StaticDateFormat);
                    }
                    else {
                        casterParserComputerForge =
                            new StringToDateTimeOffsetWExprFormatComputerForge(desc.DynamicDateFormat);
                    }
                }
                else if (targetType == typeof(DateTime) ||
                         targetType == typeof(DateTime?) ||
                         MatchesClassIdentifier("datetime")) {
                    targetType = typeof(DateTime);
                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.IsIso8601Format) {
                        casterParserComputerForge = new StringToDateTimeIsoFormatComputer();
                    }
                    else if (desc.StaticDateFormat != null) {
                        casterParserComputerForge =
                            new StringToDateTimeWStaticFormatComputer(desc.StaticDateFormat);
                    }
                    else {
                        casterParserComputerForge =
                            new StringToDateTimeWExprFormatComputerForge(desc.DynamicDateFormat);
                    }
                }
                else if (targetType == typeof(long) || targetType == typeof(long?)) {
                    targetType = typeof(long);
                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.IsIso8601Format) {
                        casterParserComputerForge = new StringToLongWStaticISOFormatComputer();
                    }
                    else if (desc.StaticDateFormat != null) {
                        casterParserComputerForge = new StringToLongWStaticFormatComputer(desc.StaticDateFormat);
                    }
                    else {
                        casterParserComputerForge = new StringToLongWExprFormatComputerForge(desc.DynamicDateFormat);
                    }
                }
                else {
                    throw new ExprValidationException(
                        "Use of the '" +
                        dateFormatParameter.ParameterName +
                        "' named parameter requires a target type of long, DateTime, DateTimeOffset or DateEx");
                }
            }
            else if (targetType != null) {
                targetType = targetType.GetBoxedType();
                caster = SimpleTypeCasterFactory.GetCaster(fromType, targetType);
                numeric = caster.IsNumericCast;
            }
            else if (MatchesClassIdentifier("bigint") || MatchesClassIdentifier("biginteger")) {
                targetType = typeof(BigInteger);
                targetType = ApplyDimensions(targetType);
                caster = SimpleTypeCasterFactory.GetCaster(fromType, targetType);
                numeric = true;
            }
            else if (MatchesClassIdentifier("decimal")) {
                targetType = typeof(decimal);
                targetType = ApplyDimensions(targetType);
                caster = SimpleTypeCasterFactory.GetCaster(fromType, targetType);
                numeric = true;
            }
            else {
                try {
                    targetType = TypeHelper.GetClassForName(
                        classIdentifier.Trim(),
                        validationContext.ImportService.ClassForNameProvider);
                }
                catch (TypeLoadException e) {
                    throw new ExprValidationException(
                        "Class as listed in cast function by name '" + classIdentifier + "' cannot be loaded",
                        e);
                }

                targetType = ApplyDimensions(targetType);
                numeric = targetType.IsNumeric();
                if (numeric) {
                    caster = SimpleTypeCasterFactory.GetCaster(fromType, targetType);
                }
                else {
                    caster = new SimpleTypeCasterAnyType(targetType);
                }
            }

            // assign a computer unless already assigned
            if (casterParserComputerForge == null) {
                // to-string
                if (targetType == typeof(string)) {
                    casterParserComputerForge = new StringXFormComputer();
                }
                else if (fromType == typeof(string) && targetType != typeof(char)) {
                    // parse
                    SimpleTypeParserSPI parser = SimpleTypeParserFactory.GetParser(targetType.GetBoxedType());
                    casterParserComputerForge = new StringParserComputer(parser);
                }
                else if (numeric) {
                    // numeric cast with check
                    casterParserComputerForge = new NumberCasterComputer(caster);
                }
                else {
                    // non-numeric cast
                    casterParserComputerForge = new NonnumericCasterComputer(caster);
                }
            }

            // determine constant or not
            object theConstant = null;
            var isConstant = false;
            if (ChildNodes[0].Forge.ForgeConstantType.IsCompileTimeConstant) {
                isConstant = casterParserComputerForge.IsConstantForConstInput;
                if (isConstant) {
                    var @in = ChildNodes[0].Forge.ExprEvaluator.Evaluate(null, true, null);
                    theConstant = @in == null
                        ? null
                        : casterParserComputerForge.EvaluatorComputer.Compute(@in, null, true, null);
                }
            }
            
            forge = new ExprCastNodeForge(this, casterParserComputerForge, targetType, isConstant, theConstant);
            return null;
        }
Ejemplo n.º 6
0
        private static object GetFinalValue(
            Type annotationClass,
            AnnotationAttribute annotationAttribute,
            object value,
            ImportServiceCompileTime importService)
        {
            if (value == null) {
                if (annotationAttribute.DefaultValue == null) {
                    throw new AnnotationException(
                        "Annotation '" +
                        annotationClass.GetSimpleName() +
                        "' requires a value for attribute '" +
                        annotationAttribute.Name +
                        "'");
                }

                return annotationAttribute.DefaultValue;
            }

            // handle non-array
            if (!annotationAttribute.AnnotationType.IsArray) {
                // handle primitive value
                if (!annotationAttribute.AnnotationType.IsAttribute()) {
                    // if expecting an enumeration type, allow string value
                    if (annotationAttribute.AnnotationType.IsEnum && (value is string valueString)) {
                        valueString = valueString.Trim();

                        var annotationType = annotationAttribute.AnnotationType;
                        try {
                            return Enum.Parse(annotationType, valueString, true);
                        }
                        catch (ArgumentException) {
                            throw new AnnotationException(
                                "Annotation '" +
                                annotationClass.FullName +
                                "' requires an enum-value '" +
                                annotationAttribute.AnnotationType.FullName +
                                "' for attribute '" +
                                annotationAttribute.Name +
                                "' but received '" +
                                value +
                                "' which is not one of the enum choices");
                        }
                    }

                    // cast as required
                    var caster = SimpleTypeCasterFactory.GetCaster(value.GetType(), annotationAttribute.AnnotationType);
                    var finalValue = caster.Cast(value);
                    if (finalValue == null) {
                        throw new AnnotationException(
                            "Annotation '" +
                            annotationClass.Name +
                            "' requires a " +
                            annotationAttribute.AnnotationType.Name +
                            "-typed value for attribute '" +
                            annotationAttribute.Name +
                            "' but received " +
                            "a " +
                            value.GetType().Name +
                            "-typed value");
                    }

                    return finalValue;
                }

                // nested annotation
                if (!(value is AnnotationDesc)) {
                    throw new AnnotationException(
                        "Annotation '" +
                        annotationClass.GetSimpleName() +
                        "' requires a " +
                        annotationAttribute.AnnotationType.GetSimpleName() +
                        "-typed value for attribute '" +
                        annotationAttribute.Name +
                        "' but received " +
                        "a " +
                        value.GetType().GetSimpleName() +
                        "-typed value");
                }

                return CreateAttributeInstance((AnnotationDesc) value, importService);
            }

            if (!(value is Array valueAsArray)) {
                throw new AnnotationException(
                    "Annotation '" +
                    annotationClass.GetSimpleName() +
                    "' requires a " +
                    annotationAttribute.AnnotationType.GetSimpleName() +
                    "-typed value for attribute '" +
                    annotationAttribute.Name +
                    "' but received " +
                    "a " +
                    value.GetType().GetSimpleName() +
                    "-typed value");
            }

            var componentType = annotationAttribute.AnnotationType.GetElementType();
            var array = Array.CreateInstance(componentType, valueAsArray.Length);

            for (var i = 0; i < valueAsArray.Length; i++) {
                var arrayValue = valueAsArray.GetValue(i);
                if (arrayValue == null) {
                    throw new AnnotationException(
                        "Annotation '" +
                        annotationClass.GetSimpleName() +
                        "' requires a " +
                        "non-null value for array elements for attribute '" +
                        annotationAttribute.Name +
                        "'");
                }

                object finalValue;
                if (arrayValue is AnnotationDesc annotationDesc) {
                    var inner = CreateAttributeInstance(annotationDesc, importService);
                    if (!componentType.IsInstanceOfType(inner)) {
                        throw MakeArrayMismatchException(
                            annotationClass,
                            componentType,
                            annotationAttribute.Name,
                            inner.GetType());
                    }

                    finalValue = inner;
                }
                else {
                    var caster = SimpleTypeCasterFactory.GetCaster(
                        arrayValue.GetType(),
                        annotationAttribute.AnnotationType.GetElementType());
                    finalValue = caster.Cast(arrayValue);
                    if (finalValue == null) {
                        throw MakeArrayMismatchException(
                            annotationClass,
                            componentType,
                            annotationAttribute.Name,
                            arrayValue.GetType());
                    }
                }

                array.SetValue(finalValue, i);
            }

            return array;
        }
Ejemplo n.º 7
0
        public VariantPropertyDesc ResolveProperty(
            string propertyName,
            EventType[] variants)
        {
            var existsInAll = true;
            Type commonType = null;
            var mustCoerce = false;
            for (var i = 0; i < variants.Length; i++) {
                var type = variants[i].GetPropertyType(propertyName).GetBoxedType();
                if (type == null) {
                    existsInAll = false;
                    continue;
                }

                if (commonType == null) {
                    commonType = type;
                    continue;
                }

                // compare types
                if (type == commonType) {
                    continue;
                }

                // coercion
                if (type.IsNumeric()) {
                    if (type.CanCoerce(commonType)) {
                        mustCoerce = true;
                        continue;
                    }

                    if (commonType.CanCoerce(type)) {
                        mustCoerce = true;
                        commonType = type;
                    }
                }
                else if (commonType == typeof(object)) {
                    continue;
                }
                else if (!type.IsBuiltinDataType()) {
                    // common interface or base class
                    ISet<Type> supersForType = new LinkedHashSet<Type>();
                    TypeHelper.GetBase(type, supersForType);
                    supersForType.Remove(typeof(object));

                    if (supersForType.Contains(commonType)) {
                        continue; // type implements or : common type
                    }

                    if (TypeHelper.IsSubclassOrImplementsInterface(commonType, type)) {
                        commonType = type; // common type implements type
                        continue;
                    }

                    // find common interface or type both implement
                    ISet<Type> supersForCommonType = new LinkedHashSet<Type>();
                    TypeHelper.GetBase(commonType, supersForCommonType);
                    supersForCommonType.Remove(typeof(object));

                    // Take common classes first, ignoring interfaces
                    var found = false;
                    foreach (var superClassType in supersForType) {
                        if (!superClassType.IsInterface && supersForCommonType.Contains(superClassType)) {
                            commonType = superClassType;
                            found = true;
                            break;
                        }
                    }

                    if (found) {
                        continue;
                    }

                    // Take common interfaces
                    foreach (var superClassType in supersForType) {
                        if (superClassType.IsInterface && supersForCommonType.Contains(superClassType)) {
                            break;
                        }
                    }
                }

                commonType = typeof(object);
            }

            if (!existsInAll) {
                return null;
            }

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

            // property numbers should start at zero since the serve as array index
            var propertyGetterCache = variantEventType.VariantPropertyGetterCache;
            propertyGetterCache.AddGetters(propertyName);

            EventPropertyGetterSPI getter;
            if (mustCoerce) {
                var caster = SimpleTypeCasterFactory.GetCaster(null, commonType);
                getter = new VariantEventPropertyGetterAnyWCast(variantEventType, propertyName, caster);
            }
            else {
                getter = new VariantEventPropertyGetterAny(variantEventType, propertyName);
            }

            return new VariantPropertyDesc(commonType, getter, true);
        }