@@ -31,6 +31,44 @@ public Expression<Func<TRoot, TRoot>> BuildExpression<TRoot>(ISelection selectio
3131 return Expression . Lambda < Func < TRoot , TRoot > > ( selectionSetExpression , parameter ) ;
3232 }
3333
34+ public Expression < Func < TRoot , TRoot > > BuildNodeExpression < TRoot > ( ISelection selection )
35+ {
36+ var rootType = typeof ( TRoot ) ;
37+ var parameter = Expression . Parameter ( rootType , "root" ) ;
38+ var requirements = selection . DeclaringOperation . Schema . Features . GetRequired < FieldRequirementsMetadata > ( ) ;
39+ var context = new Context ( parameter , rootType , requirements ) ;
40+ var root = new TypeContainer ( ) ;
41+
42+ var entityType = selection . DeclaringOperation . GetPossibleTypes ( selection ) . FirstOrDefault ( t => t . RuntimeType == typeof ( TRoot ) ) ;
43+
44+ if ( entityType is null )
45+ {
46+ throw new InvalidOperationException (
47+ $ "Unable to resolve the entity type from `{ typeof ( TRoot ) . FullName } `.") ;
48+ }
49+
50+ var typeNode = new TypeNode ( entityType . RuntimeType ) ;
51+ var selectionSet = selection . DeclaringOperation . GetSelectionSet ( selection , entityType ) ;
52+ CollectSelections ( context , selectionSet , typeNode ) ;
53+ root . TryAddNode ( typeNode ) ;
54+
55+ if ( typeNode . Nodes . Count == 0 )
56+ {
57+ TryAddAnyLeafField ( selection , typeNode ) ;
58+ }
59+
60+ CollectTypes ( context , selection , root ) ;
61+
62+ var selectionSetExpression = BuildTypeSwitchExpression ( context , root ) ;
63+
64+ if ( selectionSetExpression is null )
65+ {
66+ throw new InvalidOperationException ( "The selection set is empty." ) ;
67+ }
68+
69+ return Expression . Lambda < Func < TRoot , TRoot > > ( selectionSetExpression , parameter ) ;
70+ }
71+
3472 private void CollectTypes ( Context context , ISelection selection , TypeContainer parent )
3573 {
3674 var namedType = selection . Type . NamedType ( ) ;
@@ -49,11 +87,12 @@ private void CollectTypes(Context context, ISelection selection, TypeContainer p
4987 CollectSelections ( context , possibleSelectionSet , possibleTypeNode ) ;
5088 parent . TryAddNode ( possibleTypeNode ) ;
5189
52- if ( possibleTypeNode . Nodes . Count == 0 )
90+ if ( possibleTypeNode . Nodes . Count == 0 )
5391 {
5492 TryAddAnyLeafField ( selection , possibleTypeNode ) ;
5593 }
5694 }
95+
5796 return ;
5897 }
5998
@@ -63,7 +102,7 @@ private void CollectTypes(Context context, ISelection selection, TypeContainer p
63102 CollectSelections ( context , selectionSet , typeNode ) ;
64103 parent . TryAddNode ( typeNode ) ;
65104
66- if ( typeNode . Nodes . Count == 0 )
105+ if ( typeNode . Nodes . Count == 0 )
67106 {
68107 TryAddAnyLeafField ( selection , typeNode ) ;
69108 }
@@ -80,7 +119,7 @@ private void CollectTypes(Context context, ISelection selection, TypeContainer p
80119 foreach ( var typeNode in parent . Nodes )
81120 {
82121 var newParent = Expression . Convert ( context . Parent , typeNode . Type ) ;
83- var newContext = context with { Parent = newParent , ParentType = typeNode . Type } ;
122+ var newContext = context with { Parent = newParent , ParentType = typeNode . Type } ;
84123 var typeCondition = Expression . TypeIs ( context . Parent , typeNode . Type ) ;
85124 var selectionSet = BuildSelectionSetExpression ( newContext , typeNode ) ;
86125
@@ -225,7 +264,7 @@ private void CollectSelections(
225264 return Expression . Bind ( node . Property , propertyAccessor ) ;
226265 }
227266
228- if ( node . IsArrayOrCollection )
267+ if ( node . IsArrayOrCollection )
229268 {
230269 throw new NotSupportedException ( "List projections are not supported." ) ;
231270 }
0 commit comments