11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4- using System . Reflection ;
54using Castle . DynamicProxy ;
65
76namespace NTestDataBuilder . Lists
87{
9- public static class ListBuilderGenerator
10- {
11- static ListBuilderGenerator ( )
12- {
13- Generator = new ProxyGenerator ( true ) ;
14- }
15-
16- public static ProxyGenerator Generator { get ; private set ; }
17- }
18-
19- public static class ListBuilderExtensions
20- {
21- public static TBuilder TheFirst < TObject , TBuilder > ( this TestDataBuilder < TObject , TBuilder > b , int howMany )
22- where TObject : class
23- where TBuilder : TestDataBuilder < TObject , TBuilder > , new ( )
24- {
25- return b . ListBuilder . TheFirst ( howMany ) ;
26- }
27-
28- public static TBuilder TheNext < TObject , TBuilder > ( this TestDataBuilder < TObject , TBuilder > b , int howMany )
29- where TObject : class
30- where TBuilder : TestDataBuilder < TObject , TBuilder > , new ( )
31- {
32- return b . ListBuilder . TheNext ( howMany ) ;
33- }
34-
35- public static TBuilder TheLast < TObject , TBuilder > ( this TestDataBuilder < TObject , TBuilder > b , int howMany )
36- where TObject : class
37- where TBuilder : TestDataBuilder < TObject , TBuilder > , new ( )
38- {
39- return b . ListBuilder . TheLast ( howMany ) ;
40- }
41-
42- public static TBuilder ThePrevious < TObject , TBuilder > ( this TestDataBuilder < TObject , TBuilder > b , int howMany )
43- where TObject : class
44- where TBuilder : TestDataBuilder < TObject , TBuilder > , new ( )
45- {
46- return b . ListBuilder . ThePrevious ( howMany ) ;
47- }
48-
49- public static TBuilder All < TObject , TBuilder > ( this TestDataBuilder < TObject , TBuilder > b )
50- where TObject : class
51- where TBuilder : TestDataBuilder < TObject , TBuilder > , new ( )
52- {
53- return b . ListBuilder . All ( ) ;
54- }
55-
56- public static ListBuilder < TObject , TBuilder > With < TObject , TBuilder > ( this TestDataBuilder < TObject , TBuilder > b , Func < TBuilder , TBuilder > modifier )
57- where TObject : class
58- where TBuilder : TestDataBuilder < TObject , TBuilder > , new ( )
59- {
60- return b . ListBuilder . With ( modifier ) ;
61- }
62-
63- public static IList < TObject > BuildList < TObject , TBuilder > ( this TestDataBuilder < TObject , TBuilder > b )
64- where TObject : class
65- where TBuilder : TestDataBuilder < TObject , TBuilder > , new ( )
66- {
67- return b . ListBuilder . BuildList ( ) ;
68- }
69- }
70-
71- public class ListBuilderInterceptor < TObject , TBuilder > : IInterceptor
72- where TBuilder : TestDataBuilder < TObject , TBuilder > , new ( )
73- where TObject : class
74- {
75- private readonly ListBuilder < TObject , TBuilder > _builder ;
76-
77- public ListBuilderInterceptor ( ListBuilder < TObject , TBuilder > builder )
78- {
79- _builder = builder ;
80- }
81-
82- public void Intercept ( IInvocation invocation )
83- {
84- if ( invocation . Method . ReturnType != typeof ( TBuilder ) )
85- {
86- throw new InvalidOperationException ( "Non-fluent builder method invoked while creating a list of builders: " + invocation . Method . Name ) ;
87- }
88-
89- _builder . Execute ( invocation ) ;
90- invocation . ReturnValue = _builder . BuilderProxy ;
91- }
92- }
93-
8+ /// <summary>
9+ /// Class that builds lists of objects by proxying a list of object builders.
10+ /// </summary>
11+ /// <typeparam name="TObject">The type of object being built</typeparam>
12+ /// <typeparam name="TBuilder">The type of builder that is building the object</typeparam>
9413 public class ListBuilder < TObject , TBuilder >
9514 where TBuilder : TestDataBuilder < TObject , TBuilder > , new ( )
9615 where TObject : class
@@ -99,7 +18,7 @@ public class ListBuilder<TObject, TBuilder>
9918 private int _count = 0 ;
10019 private readonly List < TBuilder > _list ;
10120
102- public ListBuilder ( int size )
21+ internal ListBuilder ( int size )
10322 {
10423 BuilderProxy = ( TBuilder ) ListBuilderGenerator . Generator
10524 . CreateClassProxy ( typeof ( TBuilder ) , new ProxyGenerationOptions ( new EnsureAllMethodsVirtual ( ) ) , new ListBuilderInterceptor < TObject , TBuilder > ( this ) ) ;
@@ -109,43 +28,74 @@ public ListBuilder(int size)
10928 _list . Add ( new TBuilder ( ) ) ;
11029 }
11130
112- public TBuilder BuilderProxy { get ; private set ; }
31+ internal TBuilder BuilderProxy { get ; private set ; }
11332
33+ /// <summary>
34+ /// Will target the first x objects (as specified) for subsequent builder calls (or .With call).
35+ /// You can combine this with .TheNext(y) to target the next y after the first x.
36+ /// </summary>
37+ /// <param name="howMany">The first {howMany} objects should be targeted?</param>
38+ /// <returns>The builder proxy so that calls can continue to be chained</returns>
11439 public TBuilder TheFirst ( int howMany )
11540 {
11641 _start = 0 ;
11742 _count = howMany ;
11843 return BuilderProxy ;
11944 }
12045
46+ /// <summary>
47+ /// Will target the next x objects (as specified) for subsequent builder calls (or .With call).
48+ /// </summary>
49+ /// <param name="howMany">The next {howMany} objects should be targeted?</param>
50+ /// <returns>The builder proxy so that calls can continue to be chained</returns>
12151 public TBuilder TheNext ( int howMany )
12252 {
12353 _start += _count ;
12454 _count = howMany ;
12555 return BuilderProxy ;
12656 }
12757
128- public TBuilder ThePrevious ( int howMany )
58+ /// <summary>
59+ /// Will target the last x objects (as specified) for subsequent builder calls (or .With call).
60+ /// You can combine this with .ThePrevious(y) to target the previous y after the last x.
61+ /// </summary>
62+ /// <param name="howMany">The last {howMany} objects should be targeted?</param>
63+ /// <returns>The builder proxy so that calls can continue to be chained</returns>
64+ public TBuilder TheLast ( int howMany )
12965 {
130- _start -= howMany ;
66+ _start = _list . Count - howMany ;
13167 _count = howMany ;
13268 return BuilderProxy ;
13369 }
13470
135- public TBuilder TheLast ( int howMany )
71+ /// <summary>
72+ /// Will target the previous x objects (as specified) for subsequent builder calls (or .With call).
73+ /// </summary>
74+ /// <param name="howMany">The previous {howMany} objects should be targeted?</param>
75+ /// <returns>The builder proxy so that calls can continue to be chained</returns>
76+ public TBuilder ThePrevious ( int howMany )
13677 {
137- _start = _list . Count - howMany ;
78+ _start -= howMany ;
13879 _count = howMany ;
13980 return BuilderProxy ;
14081 }
14182
83+ /// <summary>
84+ /// Will target all objects for subsequent builder calls (or .With call).
85+ /// </summary>
86+ /// <returns>The builder proxy so that calls can continue to be chained</returns>
14287 public TBuilder All ( )
14388 {
14489 _start = 0 ;
14590 _count = _list . Count ;
14691 return BuilderProxy ;
14792 }
14893
94+ /// <summary>
95+ /// Will apply the given lambda expression to all builders that are currently targeted (e.g. via .TheFirst, .TheNext, etc. calls).
96+ /// </summary>
97+ /// <param name="modifier">The lambda expression to apply to the targeted builders</param>
98+ /// <returns>The builder proxy so that calls can continue to be chained</returns>
14999 public ListBuilder < TObject , TBuilder > With ( Func < TBuilder , TBuilder > modifier )
150100 {
151101 _list . Skip ( _start )
@@ -155,6 +105,10 @@ public ListBuilder<TObject, TBuilder> With(Func<TBuilder, TBuilder> modifier)
155105 return this ;
156106 }
157107
108+ /// <summary>
109+ /// Builds the list of objects by processing all of the builder calls and then calling .Build on all the builders.
110+ /// </summary>
111+ /// <returns>The list of generated objects</returns>
158112 public IList < TObject > BuildList ( )
159113 {
160114 return _list . Select ( b => b . Build ( ) ) . ToArray ( ) ;
@@ -168,23 +122,4 @@ internal void Execute(IInvocation invocation)
168122 . ForEach ( b => invocation . Method . Invoke ( b , invocation . Arguments ) ) ;
169123 }
170124 }
171-
172- public class EnsureAllMethodsVirtual : IProxyGenerationHook
173- {
174- public void MethodsInspected ( )
175- {
176- }
177-
178- public void NonProxyableMemberNotification ( Type type , MemberInfo memberInfo )
179- {
180- if ( new [ ] { "get_Any" , "Build" , "AsProxy" , "Get" , "GetOrDefault" , "Set" , "Has" , "get_ListBuilder" , "set_ListBuilder" } . Contains ( memberInfo . Name ) )
181- return ;
182- throw new InvalidOperationException ( string . Format ( "Tried to build a list with a builder who has non-virtual method. Please make {0} on type {1} virtual." , memberInfo . Name , type . Name ) ) ;
183- }
184-
185- public bool ShouldInterceptMethod ( Type type , MethodInfo methodInfo )
186- {
187- return true ;
188- }
189- }
190125}
0 commit comments