internal static Expression GetDeserializeExpressionProcessValueDeserializer(Type valueType, Expression value, Func <Expression, Expression> processOutputValue)
        {
            Expression outputValue;
            var        nsNull = FickleExpression.StaticCall("NSNull", FickleType.Define("id"), "null", null);

            if (TypeSystem.IsPrimitiveType(valueType))
            {
                ConditionalExpression ifExpression;
                var underlyingType = valueType.GetUnwrappedNullableType();

                if (underlyingType.IsNumericType() || underlyingType == typeof(bool))
                {
                    var typeToCompare = new FickleType("NSNumber");

                    if (underlyingType.IsEnum && valueType.GetUnderlyingType() == null)
                    {
                        outputValue = Expression.Convert(FickleExpression.Call(value, typeof(int), "intValue", null), valueType);
                    }
                    else
                    {
                        outputValue = Expression.Convert(value, valueType);
                    }

                    ifExpression = Expression.IfThen(Expression.TypeIs(value, typeToCompare), processOutputValue(outputValue).ToBlock());
                }
                else if (underlyingType.IsEnum)
                {
                    Expression firstIf;

                    if (valueType.IsNullable())
                    {
                        outputValue = Expression.Convert(value, valueType);

                        firstIf = Expression.IfThen(Expression.TypeIs(value, FickleType.Define("NSNumber")), processOutputValue(outputValue).ToBlock());
                    }
                    else
                    {
                        outputValue = Expression.Convert(FickleExpression.Call(value, typeof(int), "intValue", null), valueType);

                        firstIf = Expression.IfThen(Expression.TypeIs(value, FickleType.Define("NSNumber")), processOutputValue(outputValue).ToBlock());
                    }

                    var parsedValue = FickleExpression.Variable(underlyingType, "parsedValue");
                    var success     = Expression.Variable(typeof(bool), "success");

                    var parameters = new[] { new FickleParameterInfo(typeof(string), "value"), new FickleParameterInfo(underlyingType, "outValue", true) };
                    var methodInfo = new FickleMethodInfo(null, typeof(bool), TypeSystem.GetPrimitiveName(underlyingType, true) + "TryParse", parameters, true);

                    if (valueType.IsNullable())
                    {
                        outputValue = Expression.Convert(Expression.Condition(success, Expression.Convert(Expression.Convert(parsedValue, valueType), FickleType.Define("id")), Expression.Convert(FickleExpression.StaticCall(FickleType.Define("NSNull"), valueType, "null", null), FickleType.Define("id"))), valueType);
                    }
                    else
                    {
                        outputValue = Expression.Convert(parsedValue, valueType);
                    }

                    var secondIf = Expression.IfThenElse
                                   (
                        Expression.TypeIs(value, FickleType.Define("NSString")),
                        FickleExpression.Block
                        (
                            new ParameterExpression[]
                    {
                        parsedValue,
                        success
                    },
                            Expression.IfThen
                            (
                                Expression.Not(Expression.Assign(success, Expression.Call(null, methodInfo, Expression.Convert(value, typeof(string)), parsedValue))),
                                Expression.Assign(parsedValue, Expression.Convert(Expression.Constant(0), underlyingType)).ToStatementBlock()
                            ),
                            processOutputValue(outputValue)
                        ),
                        firstIf
                                   );

                    ifExpression = secondIf;
                }
                else
                {
                    ifExpression = Expression.IfThen(Expression.TypeIs(value, typeof(string)), processOutputValue(Expression.Convert(Expression.Convert(value, typeof(object)), valueType)).ToBlock());
                }

                if (valueType.IsNullable())
                {
                    ifExpression = Expression.IfThenElse
                                   (
                        Expression.Equal(value, nsNull),
                        processOutputValue(Expression.Convert(nsNull, valueType)).ToBlock(),
                        ifExpression
                                   );
                }

                return(ifExpression);
            }
            else if (valueType is FickleType && ((FickleType)valueType).ServiceClass != null)
            {
                outputValue = FickleExpression.New(valueType, "initWithPropertyDictionary", FickleExpression.Convert(value, "NSDictionary"));

                return(Expression.IfThen(Expression.TypeIs(value, FickleType.Define("NSDictionary")), processOutputValue(outputValue).ToBlock()));
            }
            else if (valueType is FickleType && ((FickleType)valueType).ServiceEnum != null)
            {
                return(Expression.IfThen(Expression.TypeIs(value, FickleType.Define("NSNumber")), processOutputValue(value).ToBlock()));
            }
            else if (valueType is FickleListType)
            {
                var listType = valueType as FickleListType;

                var arrayVar  = FickleExpression.Variable("NSMutableArray", "array");
                var variables = new[] { arrayVar };
                var arrayItem = FickleExpression.Parameter(FickleType.Define("id"), "arrayItem");

                var forEachBody = GetDeserializeExpressionProcessValueDeserializer(listType.ListElementType, arrayItem, c => FickleExpression.Call(arrayVar, "addObject", Expression.Convert(c, typeof(object))).ToStatement());

                var ifThen = Expression.IfThen
                             (
                    Expression.TypeIs(value, FickleType.Define("NSArray")),
                    FickleExpression.Block
                    (
                        variables,
                        Expression.Assign(arrayVar, FickleExpression.New("NSMutableArray", "initWithCapacity", FickleExpression.Call(Expression.Convert(value, FickleType.Define("NSArray")), typeof(int), "count", null))).ToStatement(),
                        FickleExpression.ForEach(arrayItem, value, FickleExpression.Block(forEachBody)),
                        processOutputValue(Expression.Convert(arrayVar, valueType))
                    )
                             );

                return(ifThen);
            }
            else
            {
                throw new InvalidOperationException("Unsupported property type: " + valueType);
            }
        }