public static FieldType AddIdField(this ObjectGraphType <object> type)
        {
            return(type.Field <NonNullGraphType <IdGraphType> >("id", "The global unique id of an object", null, context => {
                var node = context.Source;

                // try to find the id property (i.e. "Id" or "OrderId")
                var idPropertyInfo = node.GetType().GetIdPropertyInfo();

                // generate and return global id
                return GlobalId.ToGlobalId(node.GetType().Name, idPropertyInfo.GetValue(node).ToString());
            }));
        }
Example #2
0
 public Edge(T node)
 {
     this.Node   = node;
     this.Cursor = GlobalId.ToGlobalId(node.GetType().Name, typeof(T).GetId <TId>(node).ToString());
 }
        /// <summary>
        /// Adds all fields to a graph type by iterating through the model type properties.
        /// </summary>
        /// <typeparam name="T">The model type.</typeparam>
        /// <param name="type"></param>
        /// <param name="handleIdProperty">If set to true, the Id property is added as field. Default is false.</param>
        public static void AddFieldsFromType <T>(this ObjectGraphType <object> type, bool handleIdProperty = false)
        {
            var properties = typeof(T).GetExactProperies();

            foreach (var property in properties)
            {
                var typeName     = property.PropertyType.Name;
                var propertyName = property.Name.ToFirstLower();

                // handle Id
                if (propertyName == "id")
                {
                    // skip property named "id" if desired. May be skipped because it is handled already in NodeType.
                    if (!handleIdProperty)
                    {
                        continue;
                    }

                    type.AddIdField();
                    continue;
                }

                // convert all foreign key id fields to be global unique
                if (propertyName.EndsWith("Id"))
                {
                    type.Field <IdGraphType>(propertyName, null, null, context =>
                    {
                        var node = context.Source;
                        return(GlobalId.ToGlobalId(property.Name.Remove(propertyName.Length - 2), property.GetValue(node).ToString()));
                    });
                    continue;
                }

                // create primitive fields like ints, strings, floats etc.
                if (property.PropertyType.IsSimpleType())
                {
                    type.CreateFieldFromPrimitiveProperty(property);
                    continue;
                }

                // generate connection field for collection / list
                if (property.PropertyType.GetInterface("ICollection") != null && property.PropertyType.IsGenericType())
                {
                    // create an ObjectType<itemType>
                    var itemType    = property.PropertyType.GenericTypeArguments[0];
                    var graphQLType = typeof(NodeObjectType <>).MakeGenericType(itemType);
                    graphQLType = graphQLType.ConvertToVirtualType();

                    // construct resolver
                    Func <ResolveFieldContext <object>, object> resolver = (context) => {
                        // get the collection / list items
                        // TODO: crazy thoughts: what if this property was not loaded yet?
                        // If, for example, a list of users is loaded by a repository, the roles
                        // of each user may not have been loaded.
                        // Could it be possibe to somehow get and call a repository here and perform
                        // something like lazy loading?
                        // Further: if a collection of object is loaded, could it be easily possible to
                        // perform batch loading and have some temporaly cache for this requests?
                        var items = context.Source.GetProperyValue(propertyName);

                        // constuct a type like Connection<Order, TId>
                        var connectionType = typeof(Connection <,>);
                        var idType         = itemType.GetIdType();
                        connectionType = connectionType.MakeGenericType(new[] { itemType, idType });

                        // call like new Connection<Order, TId>(items)
                        var connection = Activator.CreateInstance(connectionType, items);
                        return(connection);
                    };

                    type.AddConnectionField(itemType, resolver, propertyName, null);

                    continue;
                }

                // create complex property fields
                var complexType = typeof(NodeObjectType <>).MakeGenericType(property.PropertyType).ConvertToVirtualType();
                type.Field(complexType, propertyName);
            }
        }
Example #4
0
 public Viewer()
 {
     this.Id = GlobalId.ToGlobalId("Viewer", Guid.NewGuid().ToString());
 }