Beispiel #1
0
        private LinkData CreateLinkDataForSubProperties(Type type, object context, string contextInfoName, string viewElementInfoName, List <PropertyInfo> propertyPath, LinkRule rule)
        {
            foreach (PropertyInfo pInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                if (!pInfo.PropertyType.IsClass || pInfo.PropertyType == typeof(string))
                {
                    continue;
                }

                object subContext;
                Type   subType;

                if (typeof(IEnumerable).IsAssignableFrom(pInfo.PropertyType))
                {
                    // if the type is a ienurable type then set the context to null because then the linker should be only informed
                    // about the found members in the generic used class
                    subContext = null;
                    subType    = pInfo.PropertyType.GetGenericArguments().First();
                }
                else if (pInfo.GetIndexParameters().Length <= 0)
                {
                    subContext = pInfo.GetValue(context);
                    subType    = pInfo.PropertyType;
                }
                else
                {
                    subContext = null;
                    subType    = pInfo.PropertyType;
                }

                LinkData data = CreateLinkData(null, rule, subType, subContext, viewElementInfoName, propertyPath, null);

                // if a match found in the sub class then return the link data.
                if (data != null)
                {
                    propertyPath.Add(pInfo);
                    return(data);
                }
            }

            return(null);
        }
Beispiel #2
0
        private LinkData CreateLinkData(string controlName, LinkRule rule, Type type, object context, string viewElementInfoName, List <PropertyInfo> propertyPath, object view)
        {
            string[] nameParts = RuleProvider.GetNameSeparatorFunc()?.Invoke(controlName ?? string.Empty) ?? null;

            if (nameParts == null || nameParts.Length == 1)
            {
                if (string.IsNullOrEmpty(controlName))
                {
                    return(null);
                }

                MemberInfo info = type.GetMember(rule.GetLinkInfoName(controlName), BindingFlags.Instance | BindingFlags.Public).FirstOrDefault();

                // if there was already a match found then create a LinkData and return it
                if (info != null)
                {
                    return(new LinkData(viewElementInfoName, info, context, propertyPath));
                }

                propertyPath = new List <PropertyInfo>();

                // if no match found then search within all properties of the passed context which are a class itself (except enumerables)
                LinkData data = CreateLinkDataForSubProperties(type, context, rule.GetLinkInfoName(controlName), viewElementInfoName, propertyPath, rule);

                if (data != null)
                {
                    data.PropertyPath = data.PropertyPath?.Reverse();
                }
                return(data);
            }
            else
            {
                propertyPath = new List <PropertyInfo>();
                Type   currentType = type;
                object lastControl = null;
                for (int i = 0; i < nameParts.Length; i++)
                {
                    // if the last of the name parts is reached then try to create the link data with the collected infos.
                    if (i == nameParts.Length - 1)
                    {
                        return(CreateLinkData(nameParts[i], rule, currentType, context, viewElementInfoName, propertyPath, view));
                    }

                    // if no last control is set then first try to find the control which is defined in this name part.
                    if (lastControl == null)
                    {
                        EnumerateFields(view.GetType(), info =>
                        {
                            if (info.Name == nameParts[i])
                            {
                                lastControl = info.GetValue(view);
                            }
                        });
                    }
                    else
                    {
                        // get the context property name for further search based on the last control and the current name part which must define the property of the control
                        // to get the context property name for further search.
                        string contextPropertyName = RuleProvider.GetContextPropertyNameForTypeAndProperty(lastControl.GetType(), nameParts[i], nameParts[i - 1]);
                        // get the property info for the context property and add it to the property path. Just assume that the property is found. It's ok if a exception occurs
                        // if the property could not be found because of e.g. typos.
                        PropertyInfo pInfo = currentType.GetProperty(contextPropertyName, BindingFlags.Instance | BindingFlags.Public);
                        propertyPath.Add(pInfo);
                        // set the current type for the next search or link creation!
                        currentType = pInfo.PropertyType;
                        lastControl = null;
                    }
                }
            }

            return(null);
        }