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()); })); }
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); } }
public Viewer() { this.Id = GlobalId.ToGlobalId("Viewer", Guid.NewGuid().ToString()); }