@@ -104,13 +104,12 @@ public IOption Add( string contextPath )
104104 case MemberExpression memExpr :
105105 var propInfo = ( PropertyInfo ) memExpr . Member ;
106106
107- if ( ! ValidateProperty ( propInfo , out var curStyle ) )
108- {
109- _logger ? . Error < string > ( "Property '{0}' is invalid" , propInfo . Name ) ;
107+ // the first PropertyInfo, which is the outermost 'leaf', must
108+ // have a public parameterless constructor and a property setter
109+ if ( ! ValidatePropertyInfo ( propInfo , firstStyle == null ) )
110110 return null ;
111- }
112111
113- firstStyle ??= curStyle ;
112+ firstStyle ??= propInfo . GetOptionStyle ( ) ;
114113
115114 propElements . Add ( propInfo ) ;
116115
@@ -124,13 +123,12 @@ public IOption Add( string contextPath )
124123 {
125124 var propInfo2 = ( PropertyInfo ) unaryMemExpr . Member ;
126125
127- if ( ! ValidateProperty ( propInfo2 , out var curStyle2 ) )
128- {
129- _logger ? . Error < string > ( "Property '{0}' is invalid" , propInfo2 . Name ) ;
126+ // the first PropertyInfo, which is the outermost 'leaf', must
127+ // have a public parameterless constructor and a property setter
128+ if ( ! ValidatePropertyInfo ( propInfo2 , firstStyle == null ) )
130129 return null ;
131- }
132130
133- firstStyle ??= curStyle2 ;
131+ firstStyle ??= propInfo2 . GetOptionStyle ( ) ;
134132
135133 propElements . Add ( propInfo2 ) ;
136134 }
@@ -161,6 +159,33 @@ public IOption Add( string contextPath )
161159 return retVal ;
162160 }
163161
162+ private bool ValidatePropertyInfo ( PropertyInfo propInfo , bool isOuterMostLeaf = false )
163+ {
164+ var piContext = new ValidationContext ( propInfo ) ;
165+
166+ var piEntry = ( ( ValidationEntry < PropertyInfo > ) piContext . Current )
167+ . HasSupportedGetter ( ) ;
168+
169+ var typeEntry = piEntry . CreateChild ( piEntry . Value . PropertyType )
170+ . IsSupportedType ( ) ;
171+
172+ if ( isOuterMostLeaf )
173+ {
174+ piEntry . HasSupportedSetter ( ) ;
175+ typeEntry . HasRequiredConstructor ( ) ;
176+ }
177+
178+ if ( piContext . IsValid )
179+ return true ;
180+
181+ foreach ( var error in piContext . Errors )
182+ {
183+ _logger ? . Error ( error . Error ) ;
184+ }
185+
186+ return false ;
187+ }
188+
164189 // determines whether or not a key is being used by an existing option, honoring whatever
165190 // case sensitivity is in use
166191 public bool UsesCommandLineKey ( string key )
@@ -195,111 +220,111 @@ IEnumerator IEnumerable.GetEnumerator()
195220 return GetEnumerator ( ) ;
196221 }
197222
198- private bool ValidateProperty ( PropertyInfo propInfo , out OptionStyle ? style )
199- {
200- style = null ;
223+ // private bool ValidateProperty( PropertyInfo propInfo, out OptionStyle? style )
224+ // {
225+ // style = null;
201226
202- if ( ! ValidateAccessMethod ( propInfo . GetMethod , propInfo . Name , 0 ) )
203- return false ;
227+ // if( !ValidateAccessMethod( propInfo.GetMethod, propInfo.Name, 0 ) )
228+ // return false;
204229
205- if ( ! ValidateAccessMethod ( propInfo . SetMethod , propInfo . Name , 1 ) )
206- return false ;
230+ // if( !ValidateAccessMethod( propInfo.SetMethod, propInfo.Name, 1 ) )
231+ // return false;
207232
208- if ( propInfo . PropertyType . IsEnum )
209- {
210- style = HasAttribute < FlagsAttribute > ( propInfo . PropertyType )
211- ? OptionStyle . ConcatenatedSingleValue
212- : OptionStyle . SingleValued ;
233+ // if( propInfo.PropertyType.IsEnum )
234+ // {
235+ // style = HasAttribute<FlagsAttribute>( propInfo.PropertyType )
236+ // ? OptionStyle.ConcatenatedSingleValue
237+ // : OptionStyle.SingleValued;
213238
214- return true ;
215- }
239+ // return true;
240+ // }
216241
217- if ( propInfo . PropertyType . IsGenericType )
218- {
219- if ( ValidateGenericType ( propInfo . PropertyType , out var innerStyle ) )
220- style = innerStyle ;
242+ // if( propInfo.PropertyType.IsGenericType )
243+ // {
244+ // if( ValidateGenericType( propInfo.PropertyType, out var innerStyle ) )
245+ // style = innerStyle;
221246
222- return style != null ;
223- }
247+ // return style != null;
248+ // }
224249
225- if ( ! ValidateType ( propInfo . PropertyType ) )
226- return false ;
250+ // if( !ValidateType( propInfo.PropertyType ) )
251+ // return false;
227252
228- style = propInfo . PropertyType . IsArray
229- ? OptionStyle . Collection
230- : typeof ( bool ) . IsAssignableFrom ( propInfo . PropertyType )
231- ? OptionStyle . Switch
232- : OptionStyle . SingleValued ;
253+ // style = propInfo.PropertyType.IsArray
254+ // ? OptionStyle.Collection
255+ // : typeof(bool).IsAssignableFrom( propInfo.PropertyType )
256+ // ? OptionStyle.Switch
257+ // : OptionStyle.SingleValued;
233258
234- return true ;
235- }
259+ // return true;
260+ // }
236261
237- private bool ValidateGenericType ( Type genType , out OptionStyle ? style )
238- {
239- style = null ;
262+ // private bool ValidateGenericType( Type genType, out OptionStyle? style )
263+ // {
264+ // style = null;
240265
241- if ( genType . GenericTypeArguments . Length != 1 )
242- {
243- _logger ? . Error < string > ( "Generic type '{0}' does not have just one generic Type argument" ,
244- genType . Name ) ;
266+ // if( genType.GenericTypeArguments.Length != 1 )
267+ // {
268+ // _logger?.Error<string>( "Generic type '{0}' does not have just one generic Type argument",
269+ // genType.Name );
245270
246- return false ;
247- }
271+ // return false;
272+ // }
248273
249- if ( ! ValidateType ( genType . GenericTypeArguments [ 0 ] ) )
250- return false ;
274+ // if( !ValidateType( genType.GenericTypeArguments[ 0 ] ) )
275+ // return false;
251276
252- if ( ! typeof ( List < > ) . MakeGenericType ( genType . GenericTypeArguments [ 0 ] ) . IsAssignableFrom ( genType ) )
253- {
254- _logger ? . Error ( "Generic type '{0}' is not a List<> type" , genType ) ;
255- return false ;
256- }
277+ // if( !typeof(List<>).MakeGenericType( genType.GenericTypeArguments[ 0 ] ).IsAssignableFrom( genType ) )
278+ // {
279+ // _logger?.Error( "Generic type '{0}' is not a List<> type", genType );
280+ // return false;
281+ // }
257282
258- style = OptionStyle . Collection ;
283+ // style = OptionStyle.Collection;
259284
260- return true ;
261- }
285+ // return true;
286+ // }
262287
263- private bool ValidateType ( Type toCheck )
264- {
265- if ( toCheck . IsGenericType )
266- return false ;
288+ // private bool ValidateType( Type toCheck )
289+ // {
290+ // if( toCheck.IsGenericType )
291+ // return false;
267292
268- if ( toCheck . IsArray )
269- return ValidateType ( toCheck . GetElementType ( ) ! ) ;
293+ // if( toCheck.IsArray )
294+ // return ValidateType( toCheck.GetElementType()! );
270295
271- if ( toCheck . IsValueType
272- || typeof ( string ) . IsAssignableFrom ( toCheck )
273- || toCheck . GetConstructors ( ) . Any ( c => c . GetParameters ( ) . Length == 0 ) )
274- return true ;
296+ // if( toCheck.IsValueType
297+ // || typeof(string).IsAssignableFrom( toCheck )
298+ // || toCheck.GetConstructors().Any( c => c.GetParameters().Length == 0 ) )
299+ // return true;
275300
276- _logger ? . Error ( "Unsupported type '{0}'" , toCheck ) ;
301+ // _logger?.Error( "Unsupported type '{0}'", toCheck );
277302
278- return false ;
279- }
303+ // return false;
304+ // }
280305
281- private bool ValidateAccessMethod ( MethodInfo ? methodInfo , string propName , int allowedParams )
282- {
283- if ( methodInfo == null )
284- {
285- _logger ? . Error < string > ( "Property '{0}' does not have a get or set method" , propName ) ;
286- return false ;
287- }
306+ // private bool ValidateAccessMethod( MethodInfo? methodInfo, string propName, int allowedParams )
307+ // {
308+ // if( methodInfo == null )
309+ // {
310+ // _logger?.Error<string>( "Property '{0}' does not have a get or set method", propName );
311+ // return false;
312+ // }
288313
289- if ( ! methodInfo . IsPublic )
290- {
291- _logger ? . Error < string , string > ( "Property '{0}::{1}' is not bindable" , propName , methodInfo . Name ) ;
292- return false ;
293- }
314+ // if( !methodInfo.IsPublic )
315+ // {
316+ // _logger?.Error<string, string>( "Property '{0}::{1}' is not bindable", propName, methodInfo.Name );
317+ // return false;
318+ // }
294319
295- if ( methodInfo . GetParameters ( ) . Length > allowedParams )
296- {
297- _logger ? . Error < string > ( "Property '{0}::{1}' is indexed" , propName , methodInfo . Name ) ;
298- return false ;
299- }
320+ // if( methodInfo.GetParameters().Length > allowedParams )
321+ // {
322+ // _logger?.Error<string>( "Property '{0}::{1}' is indexed", propName, methodInfo.Name );
323+ // return false;
324+ // }
300325
301- return true ;
302- }
326+ // return true;
327+ // }
303328
304329 private IEnumerable < string > ValidateCommandLineKeys ( string [ ] cmdLineKeys )
305330 {
@@ -325,11 +350,11 @@ private static string GetContextPath( List<PropertyInfo> propElements )
325350 ) ;
326351 }
327352
328- private static bool HasAttribute < TAttr > ( Type toCheck )
329- where TAttr : Attribute
330- {
331- return toCheck . GetCustomAttribute < TAttr > ( ) != null ;
332- }
353+ // private static bool HasAttribute<TAttr>( Type toCheck )
354+ // where TAttr : Attribute
355+ // {
356+ // return toCheck.GetCustomAttribute<TAttr>() != null;
357+ // }
333358
334359 private class TypeBoundOptionComparer : IEqualityComparer < ITypeBoundOption >
335360 {
0 commit comments