Exemplo n.º 1
0
        public static Expression CreateExpression(ExpressionType type, List <Tuple <string, Expression> > attributes)
        {
            Expression expr = null;

            switch (type)
            {
            case ExpressionType.Binding:
                expr = new BindingExpression();
                break;

            case ExpressionType.Resource:
                expr = new ResourceExpression();
                break;

            case ExpressionType.Translation:
                expr = new TranslationExpression();
                break;

            case ExpressionType.Value:
                expr = new TextExpression();
                break;
            }

            if (expr == null)
            {
                throw new ArgumentOutOfRangeException("type", type, "expecting Binding, Resource, Translation or Value");
            }

            if (attributes != null)
            {
                foreach (Tuple <string, Expression> pair in attributes)
                {
                    if (expr.IsCorrectKey(pair.Item1))
                    {
                        expr.Add(pair.Item1, pair.Item2);
                    }
                    else
                    {
                        throw new CompileException(string.Format("Unexpected attribute with key {0}", pair.Item1));
                    }
                }
            }

            return(expr);
        }
Exemplo n.º 2
0
        public static Expression CreateExpression(ExpressionType type, List<Tuple<string, Expression>> attributes)
        {
            Expression expr = null;
            switch (type)
            {
                case ExpressionType.Binding:
                    expr = new BindingExpression();
                    break;
                case ExpressionType.Resource:
                    expr = new ResourceExpression();
                    break;
                case ExpressionType.Translation:
                    expr = new TranslationExpression();
                    break;
                case ExpressionType.Value:
                    expr = new TextExpression();
                    break;
            }

            if (expr == null)
            {
                throw new ArgumentOutOfRangeException("type", type, "expecting Binding, Resource, Translation or Value");
            }

            if (attributes != null)
            {
                foreach (Tuple<string, Expression> pair in attributes)
                {
                    if (expr.IsCorrectKey(pair.Item1))
                    {
                        expr.Add(pair.Item1, pair.Item2);
                    }
                    else
                    {
                        throw new CompileException(string.Format("Unexpected attribute with key {0}", pair.Item1));
                    }
                }
            }

            return expr;
        }
        public void Preprocess(List<XmlAttribute> expressionAttributes, List<Resource> resources, List<IdViewObject> viewElements)
        {
            // Create all properties for viewElements
            foreach (IdViewObject viewElement in viewElements)
            {
                Tuple<CodeMemberField, CodeMemberProperty> result = CodeGeneratorHelper.GenerateProxyProperty(viewElement.Id, viewElement.TypeName, new CodeMethodInvokeExpression(GetFindViewByIdReference(viewElement.TypeName), CodeGeneratorHelper.GetAndroidResourceReference(ResourcePart.Id, viewElement.Id)));
                Fields.Add(result.Item1);
                Properties.Add(result.Item2);
            }

            // Generate property for ILocalizationService LocalizationService
            CodePropertyReferenceExpression localizationServiceReference = CreateLocalizationServiceProperty();

            // Eval all expressions
            List<ExpressionContainer> expressions = (from attribute in expressionAttributes
                                                     let expressionResult = EvaluateExpression(attribute.Value)
                                                     where expressionResult != null
                                                     select new ExpressionContainer
                                                    {
                                                        Expression = expressionResult,
                                                        TargetObject = attribute.AttachedId,
                                                        TargetField = attribute.LocalName,
                                                        IsTargetingResource = false,
                                                    }).ToList();
            // Affect a property name to all resources and check if some has expression as attribute value
            foreach (Resource res in resources)
            {
                res.PropertyName = NameGeneratorHelper.GetResourceName();
                foreach (KeyValuePair<string, string> propertyItem in res.Properties.Where(propertyItem => ParsingHelper.IsExpressionValue(propertyItem.Value)).ToList())
                {
                    res.Properties.Remove(propertyItem.Key);

                    Expression expr = EvaluateExpression(propertyItem.Value);
                    if (expr != null)
                    {
                        if (CheckCorrectExpressionInResource(expr))
                        {
                            Log.LogError("Expression {0} is invalid in a resource context (you cannot use binding)", propertyItem.Value);
                        }
                        else
                        {
                            expressions.Add(new ExpressionContainer
                            {
                                Expression = expr,
                                TargetObject = res.PropertyName,
                                TargetField = propertyItem.Key,
                                IsTargetingResource = true,
                            });
                        }
                    }
                }
            }

            // Check if all resources are declared and filter those we need
            Dictionary<string, Resource> neededResource = new Dictionary<string, Resource>();
            List<string> resourceKeys = expressions.SelectMany(x => GetUsedResources(x.Expression)).Distinct().ToList();
            foreach (string key in resourceKeys)
            {
                Resource res = resources.FirstOrDefault(x => key.Equals(x.Key, StringComparison.InvariantCultureIgnoreCase));
                if (res == null)
                {
                    Log.LogError("Resource with key {0} does not exists", key);
                }
                else
                {
                    neededResource.Add(key, res);
                }
            }

            // Go through all binding expression and find those where we need to declare implicit resources
            // Will also remove all Template & TemplateSelector fields in BindingExpression
            // to only have a fully prepared adapter
            foreach (Expression bindingExpression in expressions.SelectMany(expression => GetBindingExpressions(expression.Expression)).ToList())
            {
                if (bindingExpression.Has(BindingExpression.TEMPLATE))
                {
                    // create a template selector
                    string templateSelectorKey = NameGeneratorHelper.GetResourceKey();
                    string templateSelectorPropertyName = NameGeneratorHelper.GetResourceName();
                    neededResource.Add(templateSelectorKey, new Resource(templateSelectorKey)
                    {
                        PropertyName = templateSelectorPropertyName,
                        ResourceElement = null,
                        Type = Configuration.DefaultTemplateSelector
                    });
                    expressions.Add(new ExpressionContainer
                    {
                        Expression = bindingExpression[BindingExpression.TEMPLATE],
                        TargetField = Configuration.DefaultTemplateSelectorField,
                        TargetObject = templateSelectorPropertyName,
                        IsTargetingResource = true,
                    });
                    bindingExpression.Remove(BindingExpression.TEMPLATE);

                    ResourceExpression templateSelectorResourceExpression = new ResourceExpression();
                    templateSelectorResourceExpression.Add(ResourceExpression.KEY, new TextExpression
                    {
                        Value = templateSelectorKey
                    });
                    bindingExpression.Add(BindingExpression.TEMPLATE_SELECTOR, templateSelectorResourceExpression);
                }

                if (bindingExpression.Has(BindingExpression.TEMPLATE_SELECTOR))
                {
                    // create an adapter
                    string adapterKey = NameGeneratorHelper.GetResourceKey();
                    string adapterName = NameGeneratorHelper.GetResourceName();
                    neededResource.Add(adapterKey, new Resource(adapterKey)
                    {
                        PropertyName = adapterName,
                        ResourceElement = null,
                        Type = Configuration.DefaultAdapter
                    });
                    expressions.Add(new ExpressionContainer
                    {
                        Expression = bindingExpression[BindingExpression.TEMPLATE_SELECTOR],
                        TargetField = Configuration.DefaultAdapterField,
                        TargetObject = adapterName,
                        IsTargetingResource = true,
                    });
                    bindingExpression.Remove(BindingExpression.TEMPLATE_SELECTOR);
                    ResourceExpression adapterResourceExpression = new ResourceExpression();
                    adapterResourceExpression.Add(ResourceExpression.KEY, new TextExpression
                    {
                        Value = adapterKey
                    });
                    bindingExpression.Add(BindingExpression.ADAPTER, adapterResourceExpression);
                }
            }

            // In order to check if all adapter are not used more than once since we need them to be unique target
            Dictionary<string, bool> usedAdapter = new Dictionary<string, bool>();
            foreach(ExpressionContainer expression in expressions.Where(x => x.Expression.IsOfType(ExpressionType.Binding)).ToList())
            {
                Expression bindingExpression = expression.Expression;
                if (bindingExpression.Has(BindingExpression.ADAPTER))
                {
                    // expression in Adapter could only be Resource (since it's an android platform specific things, a binding expression would not have any sense)
                    Expression resourceExpression = bindingExpression[BindingExpression.ADAPTER];
                    string adapterKey = resourceExpression.GetValue(ResourceExpression.KEY);
                    Resource adapterResource = neededResource[adapterKey];

                    if (usedAdapter.ContainsKey(adapterKey))
                    {
                        Log.LogError("The adapter with key {0} is used more than once which could lead to issue, you need one adapter per use !", adapterKey);
                    }
                    else
                    {
                        usedAdapter.Add(adapterKey, true);
                    }

                    // remove the adapter property
                    bindingExpression.Remove(BindingExpression.ADAPTER);

                    // store old target info
                    string oldTargetField = expression.TargetField;
                    string oldTargetObject = expression.TargetObject;
                    bool oldTargetType = expression.IsTargetingResource;

                    // retarget the binding expression to be targeted to Adapter.Collection
                    expression.TargetField = "Collection";
                    expression.TargetObject = adapterResource.PropertyName;
                    expression.IsTargetingResource = false; //TODO : false for debug mode only, need to see what we can do about that ?

                    // add a new expression to target the old object/field couple and affect the adapter with the resource expression
                    expressions.Add(new ExpressionContainer
                    {
                        IsTargetingResource = oldTargetType,
                        TargetField = oldTargetField,
                        TargetObject = oldTargetObject,
                        Expression = resourceExpression,
                    });
                }
            }

            // Create all properties for resources
            Dictionary<string, CodePropertyReferenceExpression> resourceReferences = CreatePropertiesForResources(neededResource.Values);
            // Generate all properties to handle CommandParameter and retarget all expressions if needed
            GenerateCommandParameterProperties(expressions);

            // Create a setup resources method to initalize resources with all {Resource ...} and {Translation ...} expressions
            List<ExpressionContainer> translationExpressions = expressions.Where(x => x.Expression.IsOfType(ExpressionType.Translation)).ToList();
            List<ExpressionContainer> expressionsTargetingResources = expressions.Where(x => x.IsTargetingResource && x.Expression.IsOfType(ExpressionType.Resource)).ToList();
            List<ExpressionContainer> resourceExpressions = expressions.Where(x => !x.IsTargetingResource && x.Expression.IsOfType(ExpressionType.Resource)).ToList();
            List<ExpressionContainer> bindingExpressions = expressions.Where(x => !x.IsTargetingResource && x.Expression.IsOfType(ExpressionType.Binding)).ToList();

            CodeMethodReferenceExpression assignTranslationMethodReference = CreateAssignTranslationMethod(translationExpressions, localizationServiceReference);
            CodeMethodReferenceExpression setupResourcesReference = CreateSetupResourcesMethod(expressionsTargetingResources, resourceReferences);
            CodeMethodReferenceExpression setupResourceForViewElement = CreateSetupResourceForViewElementMethod(resourceExpressions, resourceReferences);
            CreateBindingOverrideMethod(bindingExpressions, localizationServiceReference, resourceReferences, assignTranslationMethodReference, setupResourcesReference, setupResourceForViewElement);
        }