{"action":"created","comment":{"url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/comments/215264109","pull_request_review_id":152488576,"id":215264109,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNTI2NDEwOQ==","diff_hunk":"@@ -0,0 +1,251 @@\n+﻿using System;\n+using System.Collections;\n+using System.Collections.Generic;\n+using System.Linq;\n+using System.Linq.Expressions;\n+using System.Reflection;\n+using System.Runtime.CompilerServices;\n+\n+namespace RDD.Domain.Helpers.Expressions.Utils\n+{\n+    /// <summary>\n+    /// source : http://stackoverflow.com/questions/283537/most-efficient-way-to-test-equality-of-lambda-expressions\n+    /// </summary>\n+    public static class ExpressionEqualityComparer\n+    {\n+        public static bool Eq(LambdaExpression x, LambdaExpression y) => ExpressionsEqual(x, y, null, null);\n+\n+        public static bool Eq<TSource1, TSource2, TValue>(Expression<Func<TSource1, TSource2, TValue>> x, Expression<Func<TSource1, TSource2, TValue>> y)\n+            => ExpressionsEqual(x, y, null, null);\n+\n+        public static Expression<Func<Expression<Func<TSource, TValue>>, bool>> Eq<TSource, TValue>(Expression<Func<TSource, TValue>> y)\n+            => x => ExpressionsEqual(x, y, null, null);\n+\n+        private static bool ExpressionsEqual(Expression x, Expression y, LambdaExpression rootX, LambdaExpression rootY)\n+        {\n+            if (ReferenceEquals(x, y))\n+                return true;\n+            if (x == null || y == null)\n+                return false;\n+\n+            var valueX = TryCalculateConstant(x);\n+            var valueY = TryCalculateConstant(y);\n+\n+            if (valueX.IsDefined && valueY.IsDefined)\n+                return ValuesEqual(valueX.Value, valueY.Value);\n+            \n+            if (x.NodeType != y.NodeType || !(y.Type.IsAssignableFrom(x.Type) || x.Type.IsAssignableFrom(y.Type)))\n+            {\n+                if (IsAnonymousType(x.Type) && IsAnonymousType(y.Type))\n+                    throw new NotImplementedException(\"Comparison of Anonymous Types is not supported\");\n+                return false;\n+            }\n+\n+            if (x is LambdaExpression)\n+            {\n+                var lx = (LambdaExpression)x;\n+                var ly = (LambdaExpression)y;\n+                var paramsX = lx.Parameters;\n+                var paramsY = ly.Parameters;\n+                return CollectionsEqual(paramsX, paramsY, lx, ly) && ExpressionsEqual(lx.Body, ly.Body, lx, ly);\n+            }\n+            if (x is MemberExpression)\n+            {\n+                var mex = (MemberExpression)x;\n+                var mey = (MemberExpression)y;\n+                return Equals(mex.Member, mey.Member) && ExpressionsEqual(mex.Expression, mey.Expression, rootX, rootY);\n+            }\n+            if (x is BinaryExpression)\n+            {\n+                var bx = (BinaryExpression)x;\n+                var by = (BinaryExpression)y;\n+                return bx.Method == @by.Method && ExpressionsEqual(bx.Left, @by.Left, rootX, rootY) &&\n+                       ExpressionsEqual(bx.Right, @by.Right, rootX, rootY);\n+            }\n+            if (x is UnaryExpression)\n+            {\n+                var ux = (UnaryExpression)x;\n+                var uy = (UnaryExpression)y;\n+                return ux.Method == uy.Method && ExpressionsEqual(ux.Operand, uy.Operand, rootX, rootY);\n+            }\n+            if (x is ParameterExpression)\n+            {\n+                var px = (ParameterExpression)x;\n+                var py = (ParameterExpression)y;\n+                return rootX.Parameters.IndexOf(px) == rootY.Parameters.IndexOf(py);\n+            }\n+            if (x is MethodCallExpression)\n+            {\n+                var cx = (MethodCallExpression)x;\n+                var cy = (MethodCallExpression)y;\n+                return cx.Method == cy.Method\n+                       && ExpressionsEqual(cx.Object, cy.Object, rootX, rootY)\n+                       && CollectionsEqual(cx.Arguments, cy.Arguments, rootX, rootY);\n+            }\n+            if (x is MemberInitExpression)\n+            {\n+                var mix = (MemberInitExpression)x;\n+                var miy = (MemberInitExpression)y;\n+                return ExpressionsEqual(mix.NewExpression, miy.NewExpression, rootX, rootY)\n+                       && MemberInitsEqual(mix.Bindings, miy.Bindings, rootX, rootY);\n+            }\n+            if (x is NewArrayExpression)\n+            {\n+                var nx = (NewArrayExpression)x;\n+                var ny = (NewArrayExpression)y;\n+                return CollectionsEqual(nx.Expressions, ny.Expressions, rootX, rootY);\n+            }\n+            if (x is NewExpression)","path":"Domain/RDD.Domain/Helpers/Expressions/Utils/ExpressionEqualityComparer.cs","position":98,"original_position":98,"commit_id":"abe0adb79cae02f823b9023b5313e08e724ba5b3","original_commit_id":"abe0adb79cae02f823b9023b5313e08e724ba5b3","user":{"login":"LuccaIntegration","id":24569360,"node_id":"MDQ6VXNlcjI0NTY5MzYw","avatar_url":"https://avatars0.githubusercontent.com/u/24569360?v=4","gravatar_id":"","url":"https://api.github.com/users/LuccaIntegration","html_url":"https://github.com/LuccaIntegration","followers_url":"https://api.github.com/users/LuccaIntegration/followers","following_url":"https://api.github.com/users/LuccaIntegration/following{/other_user}","gists_url":"https://api.github.com/users/LuccaIntegration/gists{/gist_id}","starred_url":"https://api.github.com/users/LuccaIntegration/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LuccaIntegration/subscriptions","organizations_url":"https://api.github.com/users/LuccaIntegration/orgs","repos_url":"https://api.github.com/users/LuccaIntegration/repos","events_url":"https://api.github.com/users/LuccaIntegration/events{/privacy}","received_events_url":"https://api.github.com/users/LuccaIntegration/received_events","type":"User","site_admin":false},"body":"![MINOR](https://sonarsource.github.io/sonar-github/severity-minor.png 'Severity: MINOR') Replace this type-check-and-cast sequence with an 'as' and a null check. [![rule](https://sonarsource.github.io/sonar-github/rule.png)](https://sonarcloud.io/coding_rules#rule_key=csharpsquid%3AS3247)\n","created_at":"2018-09-05T13:16:58Z","updated_at":"2018-09-05T13:16:58Z","html_url":"https://github.com/LuccaSA/RestDrivenDomain/pull/158#discussion_r215264109","pull_request_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/158","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/comments/215264109"},"html":{"href":"https://github.com/LuccaSA/RestDrivenDomain/pull/158#discussion_r215264109"},"pull_request":{"href":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/158"}}},"pull_request":{"url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/158","id":213230607,"node_id":"MDExOlB1bGxSZXF1ZXN0MjEzMjMwNjA3","html_url":"https://github.com/LuccaSA/RestDrivenDomain/pull/158","diff_url":"https://github.com/LuccaSA/RestDrivenDomain/pull/158.diff","patch_url":"https://github.com/LuccaSA/RestDrivenDomain/pull/158.patch","issue_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues/158","number":158,"state":"open","locked":false,"title":"Nouveau moteur de sélection de propriétés","user":{"login":"Poltuu","id":2751539,"node_id":"MDQ6VXNlcjI3NTE1Mzk=","avatar_url":"https://avatars2.githubusercontent.com/u/2751539?v=4","gravatar_id":"","url":"https://api.github.com/users/Poltuu","html_url":"https://github.com/Poltuu","followers_url":"https://api.github.com/users/Poltuu/followers","following_url":"https://api.github.com/users/Poltuu/following{/other_user}","gists_url":"https://api.github.com/users/Poltuu/gists{/gist_id}","starred_url":"https://api.github.com/users/Poltuu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Poltuu/subscriptions","organizations_url":"https://api.github.com/users/Poltuu/orgs","repos_url":"https://api.github.com/users/Poltuu/repos","events_url":"https://api.github.com/users/Poltuu/events{/privacy}","received_events_url":"https://api.github.com/users/Poltuu/received_events","type":"User","site_admin":false},"body":"Cette PR remplace le moteur de manipulation de Propriétés/Expressions, aujourd'hui incarné par `PropertySelector`, et utilisé pour la gestion des fields (serialization, include), des orderby et des filtres.\r\nElle ajoute également la gestion des includes par liste blanche sur les readonly-repository.\r\n\r\n### Summary\r\nLe nouveau système s'appuie principalement sur trois interfaces (ici en version courte)\r\n```c#\r\n    public interface IExpressionSelector  : IEquatable<IExpressionSelector>\r\n    {\r\n        string Name { get; }\r\n        LambdaExpression ToLambdaExpression();\r\n    }\r\n```\r\n```c#\r\n    public interface IExpressionSelectorChain : IExpressionSelector\r\n    {\r\n        IExpressionSelector Current { get; }\r\n        IExpressionSelectorChain Next { get; }\r\n    }\r\n```\r\n```c#\r\n    public interface IExpressionSelectorTree : IEnumerable<IExpressionSelectorChain>\r\n    {\r\n        IExpressionSelector Node { get; }\r\n        IEnumerable<IExpressionSelectorTree> Children { get; }\r\n    }\r\n```\r\n\r\nCes trois interfaces correspondent à des besoins différents:\r\n - la deserialization de la query des orderby et filtres manipule des suites de propriétés enchainées. Elles renvoient donc des `IExpressionSelectorChain`\r\n - les orderby et les filtres ont besoin d'obtenir une Expression à appliquer à un IQueryable. On leur fournit donc un `IExpressionSelector` (`IExpressionSelectorChain` implémente `IExpressionSelector`)\r\n - les includes et fields représentent un arbre de propriétés à manipuler. On leur affecte donc un `IExpressionSelectorTree`\r\n\r\n### Pourquoi est-ce bien et même mieux ?\r\nLes principaux problèmes du précédent selecteur étaient:\r\n - **nommage** brandé \"Property\". Mon nommage est orienté Expression, ce qui correspond plus à la réalité des usages et classes existantes (cf ItemExpressionSelector pour le parcours de dico) et aux besoins.\r\n - trop de **responsabilité**. Le `PropertySelector` tentait de faire à la fois le travail du `IExpressionSelectorChain`d'un `IExpressionSelector` et d'un `ExpressionSelectorParser`, ce qui aboutissaient a des apis peu claires\r\n - gestion des **égalités**. la comparaison entre PropertySelector, et les méthodes `.Contains` étaient peu performantes et douteuse (nombreux parcours de lambda, comparaison de strings..). On laisse désormais les `IExpressionSelector` se comparer elle-mêmes, souvent via un EqualityComparer.\r\n - **structure**. Depuis mai, le `PropertySelector` a une structure de chaine. C'est une avancée par rapport au précédent, dans lequel il tentait d'avoir _en plus_ une structure d'arbre. Mais du coup, le structure d'arbre, nécessaire aux include et serialization avait disparu, et rendu la gestion des include compliquée\r\n - **lisibilité**. je suis prêt à défendre que le nouveau code et logiques est plus lisible que l'ancien :)\r\n - **`Expression<Func<T, object>>`**: de nombreuses méthodes utilisaient des signatures de ce type. Ces signatures sont en réalité problématiques, car elles rajoutent un cast dans les expression, et empêchent une comparaison correcte des expressions entre elles. On utilise désormais uniquement `Expression<Func<T, TProp>>` ou `LambdaExpression `(cf APIs)\r\n - **gestion des propriétés `IEnumerable`**. Cela est une épreuve que ce nouveau moteur gère simplement, via un `EnumerablePropertySelector`\r\n\r\n@rducom m'a posé une question très juste sur ce nouveau modèle : pourquoi ne pas simplement utiliser les Expressions natives c#. Je pense que ces objets sont trop exigeants pour l'usage que nous en avons. Le moteur que je propose est plus laxiste sur certains typages et/ou noms de propriétés par exemple. Egalement, il permet d'exposer des méthodes du style `IExpressionSelectorChain.Contains(Expression<Func<TClass, TProp>> property)`, ou `IExpressionSelectorTree.Intersection(IExpressionSelectorTree tree)` plus high-level et plus facile à manipuler\r\n\r\n### APIs de constructeur\r\n\r\nVoici les apis de construction des différents objets. Des raccourcis ont été développés sur les objets concrets.\r\n```c#\r\n\r\n    public class ExpressionSelectorParser\r\n    {\r\n        IExpressionSelector Parse(Type classType, string input);\r\n        IExpressionSelector Parse<TClass>(string input);\r\n\r\n        IExpressionSelectorChain ParseChain(Type classType, string input);\r\n        IExpressionSelectorChain ParseChain<TClass>(string input);\r\n        IExpressionSelectorChain ParseChain<TClass, TProp>(Expression<Func<TClass, TProp>> lambda);\r\n\r\n        IExpressionSelectorTree ParseTree(Type classType, string input);\r\n        IExpressionSelectorTree<TClass> ParseTree<TClass>(string input);\r\n\r\n        IExpressionSelectorTree<TClass> ParseTree<TClass, TProp>(Expression<Func<TClass, TProp>> lambda);\r\n        IExpressionSelectorTree<TClass> ParseTree<TClass, TProp1, TProp2>(Expression<Func<TClass, TProp1>> lambda1, Expression<Func<TClass, TProp2>> lambda2);\r\n        IExpressionSelectorTree<TClass> ParseTree<TClass, TProp1, TProp2, TProp3>(Expression<Func<TClass, TProp1>> lambda1, Expression<Func<TClass, TProp2>> lambda2, Expression<Func<TClass, TProp3>> lambda3);\r\n        IExpressionSelectorTree<TClass> ParseTree<TClass>(params LambdaExpression[] lambdas);\r\n    }\r\n```\r\n\r\n\r\n### Remarques\r\n\r\n - **nommage**. Je ne suis pas entièrement satisfait du nommage, mais une chose délibérée qui me semble saine est l'absence du mot \"Property\". En effet, `IExpressionSelector` représente un objet capable d'exposer un LambdaExpression. Dans le cas des parcours de dictionnaire, cette lambda n'expose pas un MemberExpression, donc pas de Property. De même, ce nommage me permet de faire implémenter cette interface par `IExpressionSelectorChain` sans ambiguïté.\r\n - **généricité**. Je me suis rendu compte au fur et à mesure du développement que la généricité des objets concrets n'étaient pas nécessaire, voire source de problème. Je l'ai donc quasiment supprimé et tout fonctionne mieux\r\n\r\n**Exemples**\r\n\r\n - Avec ce nouveau modèle, la gestion des include par whiteList se résume à peau de chagrin\r\n```c#\r\n                foreach (var prop in query.Fields.Intersection(IncludeWhiteList))\r\n                {\r\n                    entities = entities.Include(prop.Name);\r\n                }\r\n```\r\n - Serialization de clés de dictionnaire. Le typage fort des `IExpressionSelector` permet\r\n```c#\r\n//before\r\n                    var value = (child as PropertySelector).Lambda.Compile().DynamicInvoke(dico);\r\n//after\r\n                    var value = dico[(child.Node as ItemSelector).Name];\r\n                    SerializeKvp(result, concreteChild.Name, value, child, null);\r\n```\r\n\r\n\r\nDe manière général, le code me parait plus claire à comprendre et facile à utiliser ainsi. Avec cette PR, RD gagne en fonctionnalité en amont du monolithe, alors que c'est d'habitude l'inverse !\r\n\r\nA vos commentaires !","created_at":"2018-09-05T09:41:56Z","updated_at":"2018-09-05T13:16:58Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b2d1637a031014cfdf9c51be31de1c271e7bc868","assignee":null,"assignees":[],"requested_reviewers":[{"login":"nfaugout","id":2686141,"node_id":"MDQ6VXNlcjI2ODYxNDE=","avatar_url":"https://avatars0.githubusercontent.com/u/2686141?v=4","gravatar_id":"","url":"https://api.github.com/users/nfaugout","html_url":"https://github.com/nfaugout","followers_url":"https://api.github.com/users/nfaugout/followers","following_url":"https://api.github.com/users/nfaugout/following{/other_user}","gists_url":"https://api.github.com/users/nfaugout/gists{/gist_id}","starred_url":"https://api.github.com/users/nfaugout/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nfaugout/subscriptions","organizations_url":"https://api.github.com/users/nfaugout/orgs","repos_url":"https://api.github.com/users/nfaugout/repos","events_url":"https://api.github.com/users/nfaugout/events{/privacy}","received_events_url":"https://api.github.com/users/nfaugout/received_events","type":"User","site_admin":false},{"login":"rducom","id":5228175,"node_id":"MDQ6VXNlcjUyMjgxNzU=","avatar_url":"https://avatars3.githubusercontent.com/u/5228175?v=4","gravatar_id":"","url":"https://api.github.com/users/rducom","html_url":"https://github.com/rducom","followers_url":"https://api.github.com/users/rducom/followers","following_url":"https://api.github.com/users/rducom/following{/other_user}","gists_url":"https://api.github.com/users/rducom/gists{/gist_id}","starred_url":"https://api.github.com/users/rducom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rducom/subscriptions","organizations_url":"https://api.github.com/users/rducom/orgs","repos_url":"https://api.github.com/users/rducom/repos","events_url":"https://api.github.com/users/rducom/events{/privacy}","received_events_url":"https://api.github.com/users/rducom/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/158/commits","review_comments_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/158/comments","review_comment_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/comments{/number}","comments_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues/158/comments","statuses_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/statuses/abe0adb79cae02f823b9023b5313e08e724ba5b3","head":{"label":"LuccaSA:new_prop_selector","ref":"new_prop_selector","sha":"abe0adb79cae02f823b9023b5313e08e724ba5b3","user":{"login":"LuccaSA","id":2686158,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2ODYxNTg=","avatar_url":"https://avatars0.githubusercontent.com/u/2686158?v=4","gravatar_id":"","url":"https://api.github.com/users/LuccaSA","html_url":"https://github.com/LuccaSA","followers_url":"https://api.github.com/users/LuccaSA/followers","following_url":"https://api.github.com/users/LuccaSA/following{/other_user}","gists_url":"https://api.github.com/users/LuccaSA/gists{/gist_id}","starred_url":"https://api.github.com/users/LuccaSA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LuccaSA/subscriptions","organizations_url":"https://api.github.com/users/LuccaSA/orgs","repos_url":"https://api.github.com/users/LuccaSA/repos","events_url":"https://api.github.com/users/LuccaSA/events{/privacy}","received_events_url":"https://api.github.com/users/LuccaSA/received_events","type":"Organization","site_admin":false},"repo":{"id":34167748,"node_id":"MDEwOlJlcG9zaXRvcnkzNDE2Nzc0OA==","name":"RestDrivenDomain","full_name":"LuccaSA/RestDrivenDomain","owner":{"login":"LuccaSA","id":2686158,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2ODYxNTg=","avatar_url":"https://avatars0.githubusercontent.com/u/2686158?v=4","gravatar_id":"","url":"https://api.github.com/users/LuccaSA","html_url":"https://github.com/LuccaSA","followers_url":"https://api.github.com/users/LuccaSA/followers","following_url":"https://api.github.com/users/LuccaSA/following{/other_user}","gists_url":"https://api.github.com/users/LuccaSA/gists{/gist_id}","starred_url":"https://api.github.com/users/LuccaSA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LuccaSA/subscriptions","organizations_url":"https://api.github.com/users/LuccaSA/orgs","repos_url":"https://api.github.com/users/LuccaSA/repos","events_url":"https://api.github.com/users/LuccaSA/events{/privacy}","received_events_url":"https://api.github.com/users/LuccaSA/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/LuccaSA/RestDrivenDomain","description":null,"fork":false,"url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain","forks_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/forks","keys_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/keys{/key_id}","collaborators_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/teams","hooks_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/hooks","issue_events_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues/events{/number}","events_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/events","assignees_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/assignees{/user}","branches_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/branches{/branch}","tags_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/tags","blobs_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/refs{/sha}","trees_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/trees{/sha}","statuses_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/statuses/{sha}","languages_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/languages","stargazers_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/stargazers","contributors_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/contributors","subscribers_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/subscribers","subscription_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/subscription","commits_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/commits{/sha}","git_commits_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/commits{/sha}","comments_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/comments{/number}","issue_comment_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues/comments{/number}","contents_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/contents/{+path}","compare_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/compare/{base}...{head}","merges_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/merges","archive_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/downloads","issues_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues{/number}","pulls_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls{/number}","milestones_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/milestones{/number}","notifications_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/labels{/name}","releases_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/releases{/id}","deployments_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/deployments","created_at":"2015-04-18T13:56:51Z","updated_at":"2018-08-22T12:09:17Z","pushed_at":"2018-09-05T13:16:52Z","git_url":"git://github.com/LuccaSA/RestDrivenDomain.git","ssh_url":"git@github.com:LuccaSA/RestDrivenDomain.git","clone_url":"https://github.com/LuccaSA/RestDrivenDomain.git","svn_url":"https://github.com/LuccaSA/RestDrivenDomain","homepage":"http://www.restdrivendomain.fr/","size":1036,"stargazers_count":4,"watchers_count":4,"language":"C#","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":52,"license":null,"forks":1,"open_issues":52,"watchers":4,"default_branch":"master"}},"base":{"label":"LuccaSA:master","ref":"master","sha":"5d1c9c08c3bf79156a5b70507428d558afc572e5","user":{"login":"LuccaSA","id":2686158,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2ODYxNTg=","avatar_url":"https://avatars0.githubusercontent.com/u/2686158?v=4","gravatar_id":"","url":"https://api.github.com/users/LuccaSA","html_url":"https://github.com/LuccaSA","followers_url":"https://api.github.com/users/LuccaSA/followers","following_url":"https://api.github.com/users/LuccaSA/following{/other_user}","gists_url":"https://api.github.com/users/LuccaSA/gists{/gist_id}","starred_url":"https://api.github.com/users/LuccaSA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LuccaSA/subscriptions","organizations_url":"https://api.github.com/users/LuccaSA/orgs","repos_url":"https://api.github.com/users/LuccaSA/repos","events_url":"https://api.github.com/users/LuccaSA/events{/privacy}","received_events_url":"https://api.github.com/users/LuccaSA/received_events","type":"Organization","site_admin":false},"repo":{"id":34167748,"node_id":"MDEwOlJlcG9zaXRvcnkzNDE2Nzc0OA==","name":"RestDrivenDomain","full_name":"LuccaSA/RestDrivenDomain","owner":{"login":"LuccaSA","id":2686158,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2ODYxNTg=","avatar_url":"https://avatars0.githubusercontent.com/u/2686158?v=4","gravatar_id":"","url":"https://api.github.com/users/LuccaSA","html_url":"https://github.com/LuccaSA","followers_url":"https://api.github.com/users/LuccaSA/followers","following_url":"https://api.github.com/users/LuccaSA/following{/other_user}","gists_url":"https://api.github.com/users/LuccaSA/gists{/gist_id}","starred_url":"https://api.github.com/users/LuccaSA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LuccaSA/subscriptions","organizations_url":"https://api.github.com/users/LuccaSA/orgs","repos_url":"https://api.github.com/users/LuccaSA/repos","events_url":"https://api.github.com/users/LuccaSA/events{/privacy}","received_events_url":"https://api.github.com/users/LuccaSA/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/LuccaSA/RestDrivenDomain","description":null,"fork":false,"url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain","forks_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/forks","keys_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/keys{/key_id}","collaborators_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/teams","hooks_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/hooks","issue_events_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues/events{/number}","events_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/events","assignees_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/assignees{/user}","branches_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/branches{/branch}","tags_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/tags","blobs_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/refs{/sha}","trees_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/trees{/sha}","statuses_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/statuses/{sha}","languages_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/languages","stargazers_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/stargazers","contributors_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/contributors","subscribers_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/subscribers","subscription_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/subscription","commits_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/commits{/sha}","git_commits_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/git/commits{/sha}","comments_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/comments{/number}","issue_comment_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues/comments{/number}","contents_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/contents/{+path}","compare_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/compare/{base}...{head}","merges_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/merges","archive_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/downloads","issues_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues{/number}","pulls_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls{/number}","milestones_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/milestones{/number}","notifications_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/labels{/name}","releases_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/releases{/id}","deployments_url":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/deployments","created_at":"2015-04-18T13:56:51Z","updated_at":"2018-08-22T12:09:17Z","pushed_at":"2018-09-05T13:16:52Z","git_url":"git://github.com/LuccaSA/RestDrivenDomain.git","ssh_url":"git@github.com:LuccaSA/RestDrivenDomain.git","clone_url":"https://github.com/LuccaSA/RestDrivenDomain.git","svn_url":"https://github.com/LuccaSA/RestDrivenDomain","homepage":"http://www.restdrivendomain.fr/","size":1036,"stargazers_count":4,"watchers_count":4,"language":"C#","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":52,"license":null,"forks":1,"open_issues":52,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/158"},"html":{"href":"https://github.com/LuccaSA/RestDrivenDomain/pull/158"},"issue":{"href":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues/158"},"comments":{"href":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/issues/158/comments"},"review_comments":{"href":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/158/comments"},"review_comment":{"href":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/pulls/158/commits"},"statuses":{"href":"https://api.github.com/repos/LuccaSA/RestDrivenDomain/statuses/abe0adb79cae02f823b9023b5313e08e724ba5b3"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"LuccaIntegration"}}