public static BindingDefinitionComposite CreateInstance(Type type, BindingDefinitionDescription definitionDescription)
        {
            try
            {
                if (string.IsNullOrEmpty(definitionDescription.Name))
                {
                    definitionDescription.Name = definitionDescription.BindingExpression.Replace('.', '_');
                    MatchCollection ret = ValidCharExtract.Matches(definitionDescription.Name);
                    StringBuilder   sb  = new StringBuilder();
                    foreach (Match m in ret)
                    {
                        sb.Append(m.Value);
                    }
                    definitionDescription.Name = sb.ToString();
                }

                definitionDescription.BindingExpression = definitionDescription.BindingExpression.Substring(1);
                definitionDescription.BindingExpression = definitionDescription.BindingExpression.Substring(0, definitionDescription.BindingExpression.Length - 1);

                BindingDefinitionComposite definition = null;
                string          bindingFormat         = definitionDescription.BindingExpression;
                List <string>   results = new List <string>();
                MatchCollection matches = Regex.Matches(bindingFormat, pattern);

                int cpt = -1;
                foreach (Match match in matches)
                {
                    string[] elements = match.Value.Split(new[] { "::" }, StringSplitOptions.None);
                    if (string.IsNullOrEmpty(elements[0]))
                    {
                        bindingFormat = bindingFormat.Replace($"{{{match.Value}}}", string.Empty);
                    }
                    else
                    {
                        int pos = results.FindIndex(s => s.Equals(elements[0]));
                        if (pos == -1)
                        {
                            results.Add(elements[0]);
                            pos = ++cpt;
                        }
                        else
                        {
                            pos = cpt;
                        }
                        string format = $"{{{match.Value}}}";
                        bindingFormat = bindingFormat.Replace(format, $"{{{pos}}}");
                    }
                }
                if (results.Count > 0)
                {
                    List <BindingDefinitionDescription> definitionDescriptions = new List <BindingDefinitionDescription>();
                    if (results.Count == 1)
                    {
                        definitionDescriptions.Add(new BindingDefinitionDescription()
                        {
                            BindingExpression = results[0], IsReadOnly = definitionDescription.IsReadOnly
                        });
                    }
                    else
                    {
                        definitionDescriptions.AddRange(results.Select(s => new BindingDefinitionDescription()
                        {
                            BindingExpression = s, IsReadOnly = true
                        }));
                    }

                    List <IBindingDefinition> nestedDefinitions = BindingDefinitionFactory.CreateInstances(type, definitionDescriptions);

                    if (nestedDefinitions.FirstOrDefault(nd => nd.IsACollection) != null)
                    {
                        throw new BindingTemplateException("The nested 'BindingDefinition' of a 'Composite BindingDefinition' cannot be a collection");
                    }

                    // If more than one nested definition, then force the Binding definition to be ReadOnly
                    definitionDescription.IsReadOnly = nestedDefinitions.Count > 1 || nestedDefinitions[0].IsReadOnly;
                    definition = new BindingDefinitionComposite(definitionDescription)
                    {
                        nestedDefinitions = nestedDefinitions, BindingFormat = bindingFormat, BindingType = typeof(string)
                    };
                    definition.canBeNotifiedNestedDefinitions = definition.nestedDefinitions.Where(d => d.CanNotify).ToList();
                    definition.CanNotify = definition.canBeNotifiedNestedDefinitions.Count > 0;
                }
                return(definition);
            }
            catch (Exception ex)
            {
                throw new BindingTemplateException($"Cannot create the 'Composite BindingDefinition' '{definitionDescription.BindingExpression}'. {ex.Message}");
            }
        }
Beispiel #2
0
        /// <summary> Create a binding definition for a given <see cref="BindingDefinitionDescription"/> of a given <see cref="Type"/> </summary>
        /// <param name="sourceType">The Type on which the '<see cref="BindingDefinitionDescription"/>' is based</param>
        /// <param name="definitionDescription">The given <see cref="Type"/></param>
        /// <returns>The newly created Binding definition or an exception is an error occurs</returns>
        internal static IBindingDefinition CreateInstance(Type sourceType, BindingDefinitionDescription definitionDescription)
        {
            if (string.IsNullOrEmpty(definitionDescription?.BindingExpression))
            {
                return(null);
            }

            try
            {
                /// Optional
                ////////////
                if (sourceType == null)
                {
                    return(BindingDefinitionOptional.CreateInstance(definitionDescription));
                }

                /// Composite
                /////////////
                if (definitionDescription.BindingExpression.StartsWith("{") && definitionDescription.BindingExpression.EndsWith("}"))
                {
                    return(BindingDefinitionComposite.CreateInstance(sourceType, definitionDescription));
                }

                /// Hierarchical
                ////////////////
                if (definitionDescription.BindingExpression.Contains("."))
                {
                    return(BindingDefinitionHierarchical.CreateInstance(sourceType, definitionDescription));
                }


                //// keyword
                ////////////
                //if (definition == null && BindingDefinitionKeyWord.KeyWords.Contains(bindingName))
                //    definition = BindingDefinitionKeyWord.CreateInstances(bindingName);


                /// Properties
                //////////////
                List <PropertyInfo> propertyInfos = (from pi in sourceType.GetProperties()
                                                     where pi.Name.Equals(definitionDescription.BindingExpression) && pi.GetGetMethod() != null && pi.GetGetMethod().IsPublic
                                                     select pi).ToList();

                if (propertyInfos != null && propertyInfos.Count > 0)
                {
                    PropertyInfo propertyInfo;
                    if (propertyInfos.Count == 1)
                    {
                        propertyInfo = propertyInfos[0];
                    }
                    else // To take the keuword 'new' into account
                    {
                        propertyInfo = propertyInfos.FirstOrDefault(pi => { MethodInfo mi = pi.GetGetMethod();
                                                                            bool isNew    = (mi.Attributes & MethodAttributes.HideBySig) == MethodAttributes.HideBySig && mi.DeclaringType.Equals(sourceType);
                                                                            return(isNew); });
                    }
                    return(BindingDefinitionProperty.CreateInstance(propertyInfo, definitionDescription));
                }

                /// Fields
                //////////
                FieldInfo fieldInfo = sourceType.GetFields().FirstOrDefault(fi => fi.Name.Equals(definitionDescription.BindingExpression) && fi.IsPublic);
                if (fieldInfo != null)
                {
                    return(BindingDefinitionField.CreateInstance(fieldInfo, definitionDescription));
                }

                /// Methods
                ///////////
                MethodInfo methodInfo = sourceType.GetMethods().FirstOrDefault(mi => mi.Name.Equals(definitionDescription.BindingExpression) && mi.IsPublic);
                if (methodInfo != null)
                {
                    return(BindingDefinitionMethod.CreateInstance(methodInfo));
                }

                return(BindingDefinitionOptional.CreateInstance(definitionDescription));
            }
            catch (Exception ex)
            {
                throw new BindingTemplateException($"Cannot create 'BindingDefinition' between '{sourceType.Name}' and '{definitionDescription.BindingExpression}'", ex);
            }
        }