/// <summary>
        /// Reflection based recursive method to populate a type with graph node values
        /// </summary>
        private object ConvertGraphToTypedObject(LabelledTreeNode <object, Term> objectGraph, Type type)
        {
            if (objectGraph.Children.Count == 0)
            {
                if (type.GetTypeInfo().IsAssignableFrom(objectGraph.Value.GetType()))
                {
                    return(objectGraph.Value);
                }
                else
                {
                    throw new InvalidCastException(string.Format("Cannot cast a {0} to a {1}", objectGraph.Value.GetType(), type));
                }
            }

            //here we use the fact that expansion types inherit from Resource
            var obj = Activator.CreateInstance(type, new[] { objectGraph.Value });

            foreach (var member in type.GetRuntimeProperties())
            {
                var memberAttribute = member.GetCustomAttribute <PropertyBindAttribute>();
                if (memberAttribute != null)
                {
                    var memberObjectGraphCollection = objectGraph.Descend(memberAttribute.Property);

                    if (member.PropertyType.IsListType())
                    {
                        var typedList = Activator.CreateInstance(member.PropertyType);
                        var addMethod = member.PropertyType.GetRuntimeMethod("Add", new Type[] { member.PropertyType.GenericTypeArguments[0] });

                        foreach (var memberObjectGraph in memberObjectGraphCollection)
                        {
                            addMethod.Invoke(typedList, new[] { ConvertGraphToTypedObject(memberObjectGraph, member.PropertyType.GenericTypeArguments[0]) });
                        }
                        member.SetValue(obj, typedList);
                    }
                    else
                    {
                        LabelledTreeNode <object, Term> memberObjectGraph = null;
                        try
                        {
                            memberObjectGraph = memberObjectGraphCollection.Single();
                        }
                        catch (Exception)
                        {
                            throw new InvalidOperationException(string.Format("The type {0} declared a non collecton property {1} but more than one node matched", type, memberAttribute.Property));
                        }
                        member.SetValue(obj, ConvertGraphToTypedObject(memberObjectGraph, member.PropertyType));
                    }
                }
            }
            return(obj);
        }
        /// <summary>
        /// Create a graph of typed objects using the type graph as a model
        /// </summary>
        private LabelledTreeNode <object, Term> TypifyGraph(LabelledTreeNode <object, Term> objectGraph, LabelledTreeNode <Type, Term> typeGraph)
        {
            var obj        = ConvertGraphToTypedObject(objectGraph, typeGraph.Value);
            var typedGraph = new LabelledTreeNode <object, Term>(obj);

            foreach (var outEdge in typeGraph.Children)
            {
                var edge              = outEdge.Edge;
                var childTypeGraph    = outEdge.TerminalNode;
                var childObjectGraphs = objectGraph.Descend(edge);

                foreach (var childObjectGraph in childObjectGraphs)
                {
                    typedGraph.AddChild(edge, TypifyGraph(childObjectGraph, childTypeGraph));
                }
            }
            return(typedGraph);
        }
Exemple #3
0
        /// <summary>
        /// Generate a bgp regex filter using the variable names in the object graph
        /// </summary>
        /// <param name="queryGraph">graph model of the query</param>
        /// <returns></returns>
        public IFilter Generate(LabelledTreeNode <object, Term> queryGraph)
        {
            var propertyInfo = typeof(T).GetPropertyInfo(_propertyLambda);

            if (propertyInfo.Name == "Id")
            {
                var variable = queryGraph.Value as Variable;
                return(variable != null ? new RegexFilter($"str({variable})", _regex) : null);
            }

            var attribute = propertyInfo.CustomAttributes.OfType <PropertyBindAttribute>().SingleOrDefault();

            if (attribute != null)
            {
                var node     = queryGraph.Descend(attribute.Property).Single();
                var variable = node.Value as Variable;
                return(variable != null ? new RegexFilter(variable.ToString(), _regex) : null);
            }

            return(null);
        }