11using System ;
22using System . Collections . Generic ;
33using System . Collections . ObjectModel ;
4+ using System . Linq ;
45using System . Reflection ;
56
67namespace Dibix . Http . Server
@@ -12,15 +13,15 @@ public abstract class HttpApiDescriptor
1213 #endregion
1314
1415 #region Properties
15- public string AreaName => this . _areaNameAccessor . Value ;
16+ public string AreaName => _areaNameAccessor . Value ;
1617 public ICollection < HttpControllerDefinition > Controllers { get ; }
1718 #endregion
1819
1920 #region Constructor
2021 protected HttpApiDescriptor ( )
2122 {
22- this . Controllers = new Collection < HttpControllerDefinition > ( ) ;
23- this . _areaNameAccessor = new Lazy < string > ( this . ResolveAreaName ) ;
23+ Controllers = new Collection < HttpControllerDefinition > ( ) ;
24+ _areaNameAccessor = new Lazy < string > ( ResolveAreaName ) ;
2425 }
2526 #endregion
2627
@@ -37,25 +38,218 @@ protected virtual string ResolveAreaName(Assembly assembly)
3738
3839 if ( String . IsNullOrEmpty ( attribute . AreaName ) )
3940 throw new InvalidOperationException ( $@ "Area name cannot be empty
40- { assembly . GetName ( ) . Name } -> { this . GetType ( ) } ") ;
41+ { assembly . GetName ( ) . Name } -> { GetType ( ) } ") ;
4142
4243 return attribute . AreaName ;
4344 }
4445
45- protected void RegisterController ( string controllerName , Action < HttpControllerDefinition > setupAction )
46+ protected void RegisterController ( string controllerName , Action < IHttpControllerDefinitionBuilder > setupAction )
4647 {
4748 Guard . IsNotNullOrEmpty ( controllerName , nameof ( controllerName ) ) ;
48- HttpControllerDefinition controller = new HttpControllerDefinition ( this . AreaName , controllerName ) ;
49- setupAction ( controller ) ;
50- this . Controllers . Add ( controller ) ;
49+ HttpControllerDefinitionBuilder builder = new HttpControllerDefinitionBuilder ( AreaName , controllerName ) ;
50+ setupAction ( builder ) ;
51+ HttpControllerDefinition controller = builder . Build ( ) ;
52+ Controllers . Add ( controller ) ;
5153 }
5254 #endregion
5355
5456 #region Private Methods
5557 private string ResolveAreaName ( )
5658 {
57- Assembly assembly = this . GetType ( ) . Assembly ;
58- return this . ResolveAreaName ( assembly ) ;
59+ Assembly assembly = GetType ( ) . Assembly ;
60+ return ResolveAreaName ( assembly ) ;
61+ }
62+ #endregion
63+
64+ #region Nested Types
65+ private sealed class HttpControllerDefinitionBuilder : IHttpControllerDefinitionBuilder
66+ {
67+ private readonly string _areaName ;
68+ private readonly string _controllerName ;
69+ private readonly IList < HttpActionDefinitionBuilder > _actions ;
70+ private readonly IList < string > _controllerImports ;
71+
72+ internal HttpControllerDefinitionBuilder ( string areaName , string controllerName )
73+ {
74+ _areaName = areaName ;
75+ _controllerName = controllerName ;
76+ _actions = new Collection < HttpActionDefinitionBuilder > ( ) ;
77+ _controllerImports = new Collection < string > ( ) ;
78+ }
79+
80+ public void AddAction ( IHttpActionTarget target , Action < IHttpActionDefinitionBuilder > setupAction )
81+ {
82+ Guard . IsNotNull ( setupAction , nameof ( setupAction ) ) ;
83+ HttpActionDefinitionBuilder builder = new HttpActionDefinitionBuilder ( _areaName , _controllerName , target ) ;
84+ setupAction ( builder ) ;
85+ _actions . Add ( builder ) ;
86+ }
87+
88+ public void Import ( string fullControllerTypeName ) => _controllerImports . Add ( fullControllerTypeName ) ;
89+
90+ public HttpControllerDefinition Build ( )
91+ {
92+ IList < HttpActionDefinition > actions = _actions . Select ( x => x . Build ( ) ) . ToArray ( ) ;
93+ HttpControllerDefinition controller = new HttpControllerDefinition ( _areaName , _controllerName , actions , _controllerImports ) ;
94+ foreach ( HttpActionDefinition action in actions )
95+ {
96+ action . Controller = controller ;
97+ }
98+ return controller ;
99+ }
100+ }
101+
102+ private sealed class HttpActionDefinitionBuilder : HttpActionBuilderBase , IHttpActionDefinitionBuilder , IHttpActionBuilderBase , IHttpParameterSourceSelector , IHttpActionDescriptor
103+ {
104+ private readonly string _areaName ;
105+ private readonly string _controllerName ;
106+ private HttpAuthorizationBuilder _authorization ;
107+ private Uri _uri ;
108+
109+ public MethodInfo Target { get ; }
110+ public HttpApiMethod Method { get ; set ; }
111+ public Uri Uri => _uri ??= new Uri ( RouteBuilder . BuildRoute ( _areaName , _controllerName , ChildRoute ) , UriKind . Relative ) ;
112+ public string ChildRoute { get ; set ; }
113+ public Type BodyContract { get ; set ; }
114+ public Type BodyBinder { get ; set ; }
115+ public bool IsAnonymous { get ; set ; }
116+ public HttpFileResponseDefinition FileResponse { get ; set ; }
117+ public string Description { get ; set ; }
118+
119+ public HttpActionDefinitionBuilder ( string areaName , string controllerName , IHttpActionTarget target )
120+ {
121+ _areaName = areaName ;
122+ _controllerName = controllerName ;
123+ Target = target . Build ( ) ;
124+ }
125+
126+ public void WithAuthorization ( IHttpActionTarget target , Action < IHttpAuthorizationBuilder > setupAction )
127+ {
128+ HttpAuthorizationBuilder builder = new HttpAuthorizationBuilder ( this , target ) ;
129+ Guard . IsNotNull ( setupAction , nameof ( setupAction ) ) ;
130+ setupAction ( builder ) ;
131+ _authorization = builder ;
132+ }
133+
134+ bool IHttpActionDescriptor . TryGetParameter ( string parameterName , out HttpParameterSource value ) => ParameterSources . TryGetValue ( parameterName , out value ) ;
135+
136+ public HttpActionDefinition Build ( )
137+ {
138+ IHttpActionExecutionMethod executor = HttpActionExecutorResolver . Compile ( this ) ;
139+ IHttpParameterResolutionMethod parameterResolver = HttpParameterResolver . Compile ( this ) ;
140+ HttpActionDefinition action = new HttpActionDefinition
141+ {
142+ Uri = Uri ,
143+ Executor = executor ,
144+ ParameterResolver = parameterResolver ,
145+ Method = Method ,
146+ ChildRoute = ChildRoute ,
147+ Body = BodyContract != null ? new HttpRequestBody ( BodyContract , BodyBinder ) : null ,
148+ IsAnonymous = IsAnonymous ,
149+ FileResponse = FileResponse ,
150+ Description = Description ,
151+ Authorization = _authorization ? . Build ( )
152+ } ;
153+ return action ;
154+ }
155+ }
156+
157+ private sealed class HttpAuthorizationBuilder : HttpActionBuilderBase , IHttpAuthorizationBuilder , IHttpActionDescriptor , IHttpActionBuilderBase , IHttpParameterSourceSelector
158+ {
159+ private readonly IHttpActionDescriptor _parent ;
160+
161+ public MethodInfo Target { get ; }
162+ public HttpApiMethod Method => _parent . Method ;
163+ public Uri Uri => _parent . Uri ;
164+ public string ChildRoute => _parent . ChildRoute ;
165+ public Type BodyContract => _parent . BodyContract ;
166+ public Type BodyBinder => _parent . BodyBinder ;
167+
168+ public HttpAuthorizationBuilder ( IHttpActionDescriptor parent , IHttpActionTarget target )
169+ {
170+ _parent = parent ;
171+ Target = target . Build ( ) ;
172+ }
173+
174+ public HttpAuthorizationDefinition Build ( )
175+ {
176+ IHttpActionExecutionMethod executor = HttpActionExecutorResolver . Compile ( this ) ;
177+ IHttpParameterResolutionMethod parameterResolver = HttpParameterResolver . Compile ( this ) ;
178+ HttpAuthorizationDefinition authorization = new HttpAuthorizationDefinition
179+ {
180+ Executor = executor ,
181+ ParameterResolver = parameterResolver ,
182+ } ;
183+ return authorization ;
184+ }
185+
186+ bool IHttpActionDescriptor . TryGetParameter ( string parameterName , out HttpParameterSource value ) => ParameterSources . TryGetValue ( parameterName , out value ) ;
187+ }
188+
189+ private abstract class HttpActionBuilderBase : HttpParameterSourceSelector , IHttpActionBuilderBase , IHttpParameterSourceSelector
190+ {
191+ public void ResolveParameterFromBody ( string targetParameterName , string bodyConverterName )
192+ {
193+ base . ResolveParameter ( targetParameterName , new HttpParameterBodySource ( bodyConverterName ) ) ;
194+ }
195+
196+ public void ResolveParameterFromSource ( string targetParameterName , string sourceName , string sourcePropertyName , Action < IHttpParameterSourceSelector > itemSources )
197+ {
198+ HttpParameterPropertySource source = base . ResolveParameterFromSourceCore ( targetParameterName , sourceName , sourcePropertyName , null ) ;
199+ if ( itemSources == null )
200+ return ;
201+
202+ HttpParameterSourceSelector sourceSelector = new HttpParameterSourceSelector ( ) ;
203+ itemSources . Invoke ( sourceSelector ) ;
204+ source . ItemSources . AddRange ( sourceSelector . ParameterSources ) ;
205+ }
206+ }
207+
208+ private class HttpParameterSourceSelector : IHttpParameterSourceSelector
209+ {
210+ internal IDictionary < string , HttpParameterSource > ParameterSources { get ; }
211+
212+ public HttpParameterSourceSelector ( )
213+ {
214+ ParameterSources = new Dictionary < string , HttpParameterSource > ( StringComparer . OrdinalIgnoreCase ) ;
215+ }
216+
217+ public void ResolveParameterFromConstant ( string targetParameterName , bool value )
218+ {
219+ ResolveParameter ( targetParameterName , new HttpParameterConstantSource ( value ) ) ;
220+ }
221+ public void ResolveParameterFromConstant ( string targetParameterName , int value )
222+ {
223+ ResolveParameter ( targetParameterName , new HttpParameterConstantSource ( value ) ) ;
224+ }
225+ public void ResolveParameterFromConstant ( string targetParameterName , string value )
226+ {
227+ ResolveParameter ( targetParameterName , new HttpParameterConstantSource ( value ) ) ;
228+ }
229+ public void ResolveParameterFromNull ( string targetParameterName )
230+ {
231+ ResolveParameter ( targetParameterName , new HttpParameterConstantSource ( null ) ) ;
232+ }
233+ public void ResolveParameterFromSource ( string targetParameterName , string sourceName , string sourcePropertyPath )
234+ {
235+ ResolveParameterFromSourceCore ( targetParameterName , sourceName , sourcePropertyPath , null ) ;
236+ }
237+ public void ResolveParameterFromSource ( string targetParameterName , string sourceName , string sourcePropertyPath , string converterName )
238+ {
239+ ResolveParameterFromSourceCore ( targetParameterName , sourceName , sourcePropertyPath , converterName ) ;
240+ }
241+
242+ protected HttpParameterPropertySource ResolveParameterFromSourceCore ( string targetParameterName , string sourceName , string sourcePropertyPath , string converterName )
243+ {
244+ HttpParameterPropertySource source = new HttpParameterPropertySource ( sourceName , sourcePropertyPath , converterName ) ;
245+ ResolveParameter ( targetParameterName , source ) ;
246+ return source ;
247+ }
248+
249+ protected void ResolveParameter ( string targetParameterName , HttpParameterSource source )
250+ {
251+ ParameterSources . Add ( targetParameterName , source ) ;
252+ }
59253 }
60254 #endregion
61255 }
0 commit comments