public VisualStudio2015SolutionTemplate(IApplication application, VisualStudioSolutionModel model, IEnumerable <IVisualStudioProject> projects)
 {
     Application    = application;
     Model          = model;
     BindingContext = new TemplateBindingContext(new VisualStudio2015SolutionTemplateModel(Application));
     Projects       = projects;
 }
Esempio n. 2
0
        private bool AllRequiredParametersHaveValue(TemplateBindingContext context)
        {
            for (var i = 0; i < _template.Parameters.Count; i++)
            {
                var parameter = _template.Parameters[i];
                if (parameter.IsOptional || parameter.IsCatchAll)
                {
                    continue;
                }

                if (!context.AcceptedValues.ContainsKey(parameter.Name))
                {
                    // We don't have a value for this parameter, so we can't generate a url.
                    return(false);
                }
            }
            return(true);
        }
Esempio n. 3
0
        private void CopyParameterDefaultValues(TemplateBindingContext context)
        {
            for (var i = 0; i < _template.Parameters.Count; i++)
            {
                var parameter = _template.Parameters[i];
                if (parameter.IsOptional || parameter.IsCatchAll)
                {
                    continue;
                }

                if (context.NeedsValue(parameter.Name))
                {
                    // Add the default value only if there isn't already a new value for it and
                    // only if it actually has a default value, which we determine based on whether
                    // the parameter value is required.
                    context.AcceptDefault(parameter.Name);
                }
            }
        }
Esempio n. 4
0
        private void CopyNonParameterAmbientValues(
            RouteValueDictionary ambientValues,
            RouteValueDictionary combinedValues,
            TemplateBindingContext context)
        {
            if (ambientValues == null)
            {
                return;
            }

            foreach (var kvp in ambientValues)
            {
                if (IsRoutePartNonEmpty(kvp.Value))
                {
                    var parameter = GetParameter(kvp.Key);
                    if (parameter == null && !context.AcceptedValues.ContainsKey(kvp.Key))
                    {
                        combinedValues.Add(kvp.Key, kvp.Value);
                    }
                }
            }
        }
Esempio n. 5
0
        internal TemplateValuesResult GetValues(
            RouteValueDictionary ambientValues,
            RouteValueDictionary explicitValues,
            IEnumerable <string> requiredKeys)
        {
            var context = new TemplateBindingContext(_defaults);

            var canCopyParameterAmbientValues = true;

            // In case a route template is not parameterized, we do not know what the required parameters are, so look
            // at required values of an endpoint to get the key names and then use them to decide if ambient values
            // should be used.
            // For example, in case of MVC it flattens out a route template like below
            //  {controller}/{action}/{id?}
            // to
            //  Products/Index/{id?},
            //  defaults: new { controller = "Products", action = "Index" },
            //  requiredValues: new { controller = "Products", action = "Index" }
            // In the above example, "controller" and "action" are no longer parameters.
            if (requiredKeys != null)
            {
                canCopyParameterAmbientValues = CanCopyParameterAmbientValues(
                    ambientValues: ambientValues,
                    explicitValues: explicitValues,
                    requiredKeys);
            }

            if (canCopyParameterAmbientValues)
            {
                // Copy ambient values when no explicit values are provided
                CopyParameterAmbientValues(
                    ambientValues: ambientValues,
                    explicitValues: explicitValues,
                    context);
            }

            // Add all remaining new values to the list of values we will use for URI generation
            CopyNonParamaterExplicitValues(explicitValues, context);

            // Accept all remaining default values if they match a required parameter
            CopyParameterDefaultValues(context);

            if (!AllRequiredParametersHaveValue(context))
            {
                return(null);
            }

            // Any default values that don't appear as parameters are treated like filters. Any new values
            // provided must match these defaults.
            if (!FiltersMatch(explicitValues))
            {
                return(null);
            }

            // Add any ambient values that don't match parameters - they need to be visible to constraints
            // but they will ignored by link generation.
            var combinedValues = new RouteValueDictionary(context.AcceptedValues);

            CopyNonParameterAmbientValues(
                ambientValues: ambientValues,
                combinedValues: combinedValues,
                context);

            return(new TemplateValuesResult()
            {
                AcceptedValues = context.AcceptedValues,
                CombinedValues = combinedValues,
            });
        }
Esempio n. 6
0
 private void CopyNonParamaterExplicitValues(RouteValueDictionary explicitValues, TemplateBindingContext context)
 {
     foreach (var kvp in explicitValues)
     {
         if (IsRoutePartNonEmpty(kvp.Value))
         {
             context.Accept(kvp.Key, kvp.Value);
         }
     }
 }
Esempio n. 7
0
        private void CopyParameterAmbientValues(
            RouteValueDictionary ambientValues,
            RouteValueDictionary explicitValues,
            TemplateBindingContext context)
        {
            // Find out which entries in the URI are valid for the URI we want to generate.
            // If the URI had ordered parameters a="1", b="2", c="3" and the new values
            // specified that b="9", then we need to invalidate everything after it. The new
            // values should then be a="1", b="9", c=<no value>.
            //
            // We also handle the case where a parameter is optional but has no value - we shouldn't
            // accept additional parameters that appear *after* that parameter.

            for (var i = 0; i < _template.Parameters.Count; i++)
            {
                var parameter = _template.Parameters[i];

                // If it's a parameter subsegment, examine the current value to see if it matches the new value
                var parameterName = parameter.Name;

                var hasExplicitValue = explicitValues.TryGetValue(parameterName, out var explicitValue);

                object ambientValue    = null;
                var    hasAmbientValue = ambientValues != null &&
                                         ambientValues.TryGetValue(parameterName, out ambientValue);

                if (hasExplicitValue && hasAmbientValue && !RoutePartsEqual(ambientValue, explicitValue))
                {
                    // Stop copying current values when we find one that doesn't match
                    break;
                }

                if (!hasExplicitValue &&
                    !hasAmbientValue &&
                    _defaults?.ContainsKey(parameter.Name) != true)
                {
                    // This is an unsatisfied parameter value and there are no defaults. We might still
                    // be able to generate a URL but we should stop 'accepting' ambient values.
                    //
                    // This might be a case like:
                    //  template: a/{b?}/{c?}
                    //  ambient: { c = 17 }
                    //  values: { }
                    //
                    // We can still generate a URL from this ("/a") but we shouldn't accept 'c' because
                    // we can't use it.
                    //
                    // In the example above we should fall into this block for 'b'.
                    break;
                }

                // If the parameter is a match, add it to the list of values we will use for URI generation
                if (hasExplicitValue)
                {
                    if (IsRoutePartNonEmpty(explicitValue))
                    {
                        context.Accept(parameterName, explicitValue);
                    }
                }
                else if (hasAmbientValue)
                {
                    context.Accept(parameterName, ambientValue);
                }
            }
        }
Esempio n. 8
0
        // Step 1: Get the list of values we're going to try to use to match and generate this URI
        public TemplateValuesResult GetValues(IDictionary <string, object> ambientValues,
                                              IDictionary <string, object> values)
        {
            var context = new TemplateBindingContext(_defaults, values);

            // Find out which entries in the URI are valid for the URI we want to generate.
            // If the URI had ordered parameters a="1", b="2", c="3" and the new values
            // specified that b="9", then we need to invalidate everything after it. The new
            // values should then be a="1", b="9", c=<no value>.
            for (var i = 0; i < _template.Parameters.Count; i++)
            {
                var parameter = _template.Parameters[i];

                // If it's a parameter subsegment, examine the current value to see if it matches the new value
                var parameterName = parameter.Name;

                object newParameterValue;
                var    hasNewParameterValue = values.TryGetValue(parameterName, out newParameterValue);

                object currentParameterValue    = null;
                var    hasCurrentParameterValue = ambientValues != null &&
                                                  ambientValues.TryGetValue(parameterName, out currentParameterValue);

                if (hasNewParameterValue && hasCurrentParameterValue)
                {
                    if (!RoutePartsEqual(currentParameterValue, newParameterValue))
                    {
                        // Stop copying current values when we find one that doesn't match
                        break;
                    }
                }

                // If the parameter is a match, add it to the list of values we will use for URI generation
                if (hasNewParameterValue)
                {
                    if (IsRoutePartNonEmpty(newParameterValue))
                    {
                        context.Accept(parameterName, newParameterValue);
                    }
                }
                else
                {
                    if (hasCurrentParameterValue)
                    {
                        context.Accept(parameterName, currentParameterValue);
                    }
                }
            }

            // Add all remaining new values to the list of values we will use for URI generation
            foreach (var kvp in values)
            {
                if (IsRoutePartNonEmpty(kvp.Value))
                {
                    context.Accept(kvp.Key, kvp.Value);
                }
            }

            // Accept all remaining default values if they match a required parameter
            for (var i = 0; i < _template.Parameters.Count; i++)
            {
                var parameter = _template.Parameters[i];
                if (parameter.IsOptional || parameter.IsCatchAll)
                {
                    continue;
                }

                if (context.NeedsValue(parameter.Name))
                {
                    // Add the default value only if there isn't already a new value for it and
                    // only if it actually has a default value, which we determine based on whether
                    // the parameter value is required.
                    context.AcceptDefault(parameter.Name);
                }
            }

            // Validate that all required parameters have a value.
            for (var i = 0; i < _template.Parameters.Count; i++)
            {
                var parameter = _template.Parameters[i];
                if (parameter.IsOptional || parameter.IsCatchAll)
                {
                    continue;
                }

                if (!context.AcceptedValues.ContainsKey(parameter.Name))
                {
                    // We don't have a value for this parameter, so we can't generate a url.
                    return(null);
                }
            }

            // Any default values that don't appear as parameters are treated like filters. Any new values
            // provided must match these defaults.
            if (context.Filters != null)
            {
                foreach (var filter in context.Filters)
                {
                    var parameter = GetParameter(filter.Key);
                    if (parameter != null)
                    {
                        continue;
                    }

                    object value;
                    if (values.TryGetValue(filter.Key, out value))
                    {
                        if (!RoutePartsEqual(value, filter.Value))
                        {
                            // If there is a non-parameterized value in the route and there is a
                            // new value for it and it doesn't match, this route won't match.
                            return(null);
                        }
                    }
                }
            }

            // Add any ambient values that don't match parameters - they need to be visible to constraints
            // but they will ignored by link generation.
            var combinedValues = new RouteValueDictionary(context.AcceptedValues);

            if (ambientValues != null)
            {
                foreach (var kvp in ambientValues)
                {
                    if (IsRoutePartNonEmpty(kvp.Value))
                    {
                        var parameter = GetParameter(kvp.Key);
                        if (parameter == null && !context.AcceptedValues.ContainsKey(kvp.Key))
                        {
                            combinedValues.Add(kvp.Key, kvp.Value);
                        }
                    }
                }
            }

            return(new TemplateValuesResult()
            {
                AcceptedValues = context.AcceptedValues,
                CombinedValues = combinedValues,
            });
        }
Esempio n. 9
0
        // Step 1: Get the list of values we're going to try to use to match and generate this URI
        public TemplateValuesResult GetValues(RouteValueDictionary ambientValues, RouteValueDictionary values)
        {
            var context = new TemplateBindingContext(_defaults);

            // Find out which entries in the URI are valid for the URI we want to generate.
            // If the URI had ordered parameters a="1", b="2", c="3" and the new values
            // specified that b="9", then we need to invalidate everything after it. The new
            // values should then be a="1", b="9", c=<no value>.
            for (var i = 0; i < _template.Parameters.Count; i++)
            {
                var parameter = _template.Parameters[i];

                // If it's a parameter subsegment, examine the current value to see if it matches the new value
                var parameterName = parameter.Name;

                object newParameterValue;
                var hasNewParameterValue = values.TryGetValue(parameterName, out newParameterValue);

                object currentParameterValue = null;
                var hasCurrentParameterValue = ambientValues != null &&
                                               ambientValues.TryGetValue(parameterName, out currentParameterValue);

                if (hasNewParameterValue && hasCurrentParameterValue)
                {
                    if (!RoutePartsEqual(currentParameterValue, newParameterValue))
                    {
                        // Stop copying current values when we find one that doesn't match
                        break;
                    }
                }

                // If the parameter is a match, add it to the list of values we will use for URI generation
                if (hasNewParameterValue)
                {
                    if (IsRoutePartNonEmpty(newParameterValue))
                    {
                        context.Accept(parameterName, newParameterValue);
                    }
                }
                else
                {
                    if (hasCurrentParameterValue)
                    {
                        context.Accept(parameterName, currentParameterValue);
                    }
                }
            }

            // Add all remaining new values to the list of values we will use for URI generation
            foreach (var kvp in values)
            {
                if (IsRoutePartNonEmpty(kvp.Value))
                {
                    context.Accept(kvp.Key, kvp.Value);
                }
            }

            // Accept all remaining default values if they match a required parameter
            for (var i = 0; i < _template.Parameters.Count; i++)
            {
                var parameter = _template.Parameters[i];
                if (parameter.IsOptional || parameter.IsCatchAll)
                {
                    continue;
                }

                if (context.NeedsValue(parameter.Name))
                {
                    // Add the default value only if there isn't already a new value for it and
                    // only if it actually has a default value, which we determine based on whether
                    // the parameter value is required.
                    context.AcceptDefault(parameter.Name);
                }
            }

            // Validate that all required parameters have a value.
            for (var i = 0; i < _template.Parameters.Count; i++)
            {
                var parameter = _template.Parameters[i];
                if (parameter.IsOptional || parameter.IsCatchAll)
                {
                    continue;
                }

                if (!context.AcceptedValues.ContainsKey(parameter.Name))
                {
                    // We don't have a value for this parameter, so we can't generate a url.
                    return null;
                }
            }

            // Any default values that don't appear as parameters are treated like filters. Any new values
            // provided must match these defaults.
            foreach (var filter in _filters)
            {
                var parameter = GetParameter(filter.Key);
                if (parameter != null)
                {
                    continue;
                }

                object value;
                if (values.TryGetValue(filter.Key, out value))
                {
                    if (!RoutePartsEqual(value, filter.Value))
                    {
                        // If there is a non-parameterized value in the route and there is a
                        // new value for it and it doesn't match, this route won't match.
                        return null;
                    }
                }
            }

            // Add any ambient values that don't match parameters - they need to be visible to constraints
            // but they will ignored by link generation.
            var combinedValues = new RouteValueDictionary(context.AcceptedValues);
            if (ambientValues != null)
            {
                foreach (var kvp in ambientValues)
                {
                    if (IsRoutePartNonEmpty(kvp.Value))
                    {
                        var parameter = GetParameter(kvp.Key);
                        if (parameter == null && !context.AcceptedValues.ContainsKey(kvp.Key))
                        {
                            combinedValues.Add(kvp.Key, kvp.Value);
                        }
                    }
                }
            }

            return new TemplateValuesResult()
            {
                AcceptedValues = context.AcceptedValues,
                CombinedValues = combinedValues,
            };
        }
Esempio n. 10
0
        // Step 1: Get the list of values we're going to try to use to match and generate this URI
        public (DispatcherValueCollection acceptedValues, DispatcherValueCollection combinedValues) GetValues(DispatcherValueCollection ambientValues, DispatcherValueCollection values)
        {
            var context = new TemplateBindingContext(_defaults);

            // Find out which entries in the URI are valid for the URI we want to generate.
            // If the URI had ordered parameters a="1", b="2", c="3" and the new values
            // specified that b="9", then we need to invalidate everything after it. The new
            // values should then be a="1", b="9", c=<no value>.
            //
            // We also handle the case where a parameter is optional but has no value - we shouldn't
            // accept additional parameters that appear *after* that parameter.
            for (var i = 0; i < _pattern.Parameters.Count; i++)
            {
                var parameter = _pattern.Parameters[i];

                // If it's a parameter subsegment, examine the current value to see if it matches the new value
                var parameterName = parameter.Name;

                var hasNewParameterValue = values.TryGetValue(parameterName, out var newParameterValue);

                object currentParameterValue    = null;
                var    hasCurrentParameterValue = ambientValues != null &&
                                                  ambientValues.TryGetValue(parameterName, out currentParameterValue);

                if (hasNewParameterValue && hasCurrentParameterValue)
                {
                    if (!RoutePartsEqual(currentParameterValue, newParameterValue))
                    {
                        // Stop copying current values when we find one that doesn't match
                        break;
                    }
                }

                if (!hasNewParameterValue &&
                    !hasCurrentParameterValue &&
                    _defaults?.ContainsKey(parameter.Name) != true)
                {
                    // This is an unsatisfied parameter value and there are no defaults. We might still
                    // be able to generate a URL but we should stop 'accepting' ambient values.
                    //
                    // This might be a case like:
                    //  template: a/{b?}/{c?}
                    //  ambient: { c = 17 }
                    //  values: { }
                    //
                    // We can still generate a URL from this ("/a") but we shouldn't accept 'c' because
                    // we can't use it.
                    //
                    // In the example above we should fall into this block for 'b'.
                    break;
                }

                // If the parameter is a match, add it to the list of values we will use for URI generation
                if (hasNewParameterValue)
                {
                    if (IsRoutePartNonEmpty(newParameterValue))
                    {
                        context.Accept(parameterName, newParameterValue);
                    }
                }
                else
                {
                    if (hasCurrentParameterValue)
                    {
                        context.Accept(parameterName, currentParameterValue);
                    }
                }
            }

            // Add all remaining new values to the list of values we will use for URI generation
            foreach (var kvp in values)
            {
                if (IsRoutePartNonEmpty(kvp.Value))
                {
                    context.Accept(kvp.Key, kvp.Value);
                }
            }

            // Accept all remaining default values if they match a required parameter
            for (var i = 0; i < _pattern.Parameters.Count; i++)
            {
                var parameter = _pattern.Parameters[i];
                if (parameter.IsOptional || parameter.IsCatchAll)
                {
                    continue;
                }

                if (context.NeedsValue(parameter.Name))
                {
                    // Add the default value only if there isn't already a new value for it and
                    // only if it actually has a default value, which we determine based on whether
                    // the parameter value is required.
                    context.AcceptDefault(parameter.Name);
                }
            }

            // Validate that all required parameters have a value.
            for (var i = 0; i < _pattern.Parameters.Count; i++)
            {
                var parameter = _pattern.Parameters[i];
                if (parameter.IsOptional || parameter.IsCatchAll)
                {
                    continue;
                }

                if (!context.AcceptedValues.ContainsKey(parameter.Name))
                {
                    // We don't have a value for this parameter, so we can't generate a url.
                    return(null, null);
                }
            }

            // Any default values that don't appear as parameters are treated like filters. Any new values
            // provided must match these defaults.
            foreach (var filter in _filters)
            {
                var parameter = _pattern.GetParameter(filter.Key);
                if (parameter != null)
                {
                    continue;
                }

                if (values.TryGetValue(filter.Key, out var value))
                {
                    if (!RoutePartsEqual(value, filter.Value))
                    {
                        // If there is a non-parameterized value in the route and there is a
                        // new value for it and it doesn't match, this route won't match.
                        return(null, null);
                    }
                }
            }

            // Add any ambient values that don't match parameters - they need to be visible to constraints
            // but they will ignored by link generation.
            var combinedValues = new DispatcherValueCollection(context.AcceptedValues);

            if (ambientValues != null)
            {
                foreach (var kvp in ambientValues)
                {
                    if (IsRoutePartNonEmpty(kvp.Value))
                    {
                        var parameter = _pattern.GetParameter(kvp.Key);
                        if (parameter == null && !context.AcceptedValues.ContainsKey(kvp.Key))
                        {
                            combinedValues.Add(kvp.Key, kvp.Value);
                        }
                    }
                }
            }

            return(context.AcceptedValues, combinedValues);
        }