@@ -248,26 +248,26 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
248
248
/// </summary>
249
249
public static implicit operator string [ ] ( CommandLinePropertyValue propertyValue ) => propertyValue . _values switch
250
250
{
251
- { Count : 0 } => Array . Empty < string > ( ) ,
252
- { } values => values . ToArray ( ) ,
251
+ { Count : 0 } => [ ] ,
252
+ { } values => [ .. SplitValues ( values ) ] ,
253
253
} ;
254
254
255
255
/// <summary>
256
256
/// 将从命令行解析出来的属性值转换为不可变字符串数组。
257
257
/// </summary>
258
258
public static implicit operator ImmutableArray < string > ( CommandLinePropertyValue propertyValue ) => propertyValue . _values switch
259
259
{
260
- { Count : 0 } => ImmutableArray < string > . Empty ,
261
- { } values => values . ToImmutableArray ( ) ,
260
+ { Count : 0 } => [ ] ,
261
+ { } values => [ .. SplitValues ( values ) ] ,
262
262
} ;
263
263
264
264
/// <summary>
265
265
/// 将从命令行解析出来的属性值转换为不可变字符串哈希集合。
266
266
/// </summary>
267
267
public static implicit operator ImmutableHashSet < string > ( CommandLinePropertyValue propertyValue ) => propertyValue . _values switch
268
268
{
269
- { Count : 0 } => ImmutableHashSet < string > . Empty ,
270
- { } values => values . ToImmutableHashSet ( ) ,
269
+ { Count : 0 } => [ ] ,
270
+ { } values => [ .. SplitValues ( values ) ] ,
271
271
} ;
272
272
273
273
/// <summary>
@@ -276,17 +276,13 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
276
276
public static implicit operator Collection < string > ( CommandLinePropertyValue propertyValue ) => propertyValue . _values switch
277
277
{
278
278
{ Count : 0 } => [ ] ,
279
- { } values => [ ..values ] ,
279
+ { } values => [ ..SplitValues ( values ) ] ,
280
280
} ;
281
281
282
282
/// <summary>
283
283
/// 将从命令行解析出来的属性值转换为字符串列表。
284
284
/// </summary>
285
- public static implicit operator List < string > ( CommandLinePropertyValue propertyValue ) => propertyValue . _values switch
286
- {
287
- { Count : 0 } => [ ] ,
288
- { } values => values . ToList ( ) ,
289
- } ;
285
+ public static implicit operator List < string > ( CommandLinePropertyValue propertyValue ) => propertyValue . ToList ( ) ;
290
286
291
287
/// <summary>
292
288
/// 将从命令行解析出来的属性值转换为字符串键值对。
@@ -298,11 +294,6 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
298
294
/// </summary>
299
295
public static implicit operator Dictionary < string , string > ( CommandLinePropertyValue propertyValue ) => propertyValue . ToDictionary ( ) ;
300
296
301
- /// <summary>
302
- /// 将从命令行解析出来的属性值以只读列表的形式访问。
303
- /// </summary>
304
- public IReadOnlyList < string > AsReadOnlyList ( ) => _values ;
305
-
306
297
/// <summary>
307
298
/// 将从命令行解析出来的属性值转换为枚举值。
308
299
/// </summary>
@@ -318,7 +309,7 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
318
309
public List < string > ToList ( ) => _values switch
319
310
{
320
311
{ Count : 0 } => [ ] ,
321
- { } values => values . ToList ( ) ,
312
+ { } values => [ .. SplitValues ( values ) ] ,
322
313
} ;
323
314
324
315
/// <summary>
@@ -342,6 +333,232 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
342
333
. GroupBy ( x => x . Key )
343
334
. ToDictionary ( x => x . Key , x => x . Last ( ) . Value ) ,
344
335
} ;
336
+
337
+ private static IEnumerable < string > SplitValues ( IReadOnlyList < string > commandLineValues )
338
+ {
339
+ for ( var commandLineValueIndex = 0 ; commandLineValueIndex < commandLineValues . Count ; commandLineValueIndex ++ )
340
+ {
341
+ var optionValue = commandLineValues [ commandLineValueIndex ] ;
342
+ var lastPart = ListValueParsingType . Start ;
343
+ var thisPartStartIndex = 0 ;
344
+ for ( var index = 0 ; index < optionValue . Length ; index ++ )
345
+ {
346
+ var c = optionValue [ index ] ;
347
+
348
+ // 引号
349
+ if ( c is '"' )
350
+ {
351
+ if ( lastPart is ListValueParsingType . Start )
352
+ {
353
+ // 开始的引号
354
+ lastPart = ListValueParsingType . QuoteStart ;
355
+ continue ;
356
+ }
357
+ if ( lastPart is ListValueParsingType . QuoteStart )
358
+ {
359
+ // 连续出现的引号
360
+ yield return "" ;
361
+ lastPart = ListValueParsingType . QuoteEnd ;
362
+ continue ;
363
+ }
364
+ if ( lastPart is ListValueParsingType . QuotedValue )
365
+ {
366
+ // 引号中值后的引号
367
+ yield return optionValue [ thisPartStartIndex ..index ] ;
368
+ lastPart = ListValueParsingType . QuoteEnd ;
369
+ continue ;
370
+ }
371
+ if ( lastPart is ListValueParsingType . QuotedSeparator )
372
+ {
373
+ // 引号中分割符后的引号
374
+ yield return "" ;
375
+ lastPart = ListValueParsingType . QuotedValue ;
376
+ continue ;
377
+ }
378
+ if ( lastPart is ListValueParsingType . QuoteEnd )
379
+ {
380
+ // 引号结束后的引号
381
+ lastPart = ListValueParsingType . QuoteStart ;
382
+ continue ;
383
+ }
384
+ if ( lastPart is ListValueParsingType . Value )
385
+ {
386
+ // 正常值后的引号
387
+ throw new CommandLineParseValueException (
388
+ $ "Invalid value format at index [{ index } ]: { optionValue } ") ;
389
+ }
390
+ if ( lastPart is ListValueParsingType . Separator )
391
+ {
392
+ // 正常分隔符后的引号
393
+ lastPart = ListValueParsingType . QuoteStart ;
394
+ continue ;
395
+ }
396
+ }
397
+
398
+ // 分割符
399
+ if ( c is ';' or ',' )
400
+ {
401
+ if ( lastPart is ListValueParsingType . Start )
402
+ {
403
+ // 开始的分割符
404
+ yield return "" ;
405
+ lastPart = ListValueParsingType . Separator ;
406
+ continue ;
407
+ }
408
+ if ( lastPart is ListValueParsingType . QuoteStart )
409
+ {
410
+ // 引号后紧跟着的分割符(等同于正常字符)
411
+ lastPart = ListValueParsingType . QuotedValue ;
412
+ continue ;
413
+ }
414
+ if ( lastPart is ListValueParsingType . QuotedValue )
415
+ {
416
+ // 引号中值后的分割符(等同于正常字符)
417
+ lastPart = ListValueParsingType . QuotedValue ;
418
+ continue ;
419
+ }
420
+ if ( lastPart is ListValueParsingType . QuotedSeparator )
421
+ {
422
+ // 引号中连续出现的分割符(等同于正常字符)
423
+ lastPart = ListValueParsingType . QuotedValue ;
424
+ continue ;
425
+ }
426
+ if ( lastPart is ListValueParsingType . QuoteEnd )
427
+ {
428
+ // 引号结束后的分割符
429
+ lastPart = ListValueParsingType . Separator ;
430
+ continue ;
431
+ }
432
+ if ( lastPart is ListValueParsingType . Value )
433
+ {
434
+ // 正常值后的分割符
435
+ yield return optionValue [ thisPartStartIndex ..index ] ;
436
+ lastPart = ListValueParsingType . Separator ;
437
+ continue ;
438
+ }
439
+ if ( lastPart is ListValueParsingType . Separator )
440
+ {
441
+ // 连续出现的分割符
442
+ yield return "" ;
443
+ lastPart = ListValueParsingType . Separator ;
444
+ continue ;
445
+ }
446
+ }
447
+
448
+ // 其他字符
449
+ if ( lastPart is ListValueParsingType . Start )
450
+ {
451
+ // 开始的值
452
+ thisPartStartIndex = index ;
453
+ lastPart = ListValueParsingType . Value ;
454
+ continue ;
455
+ }
456
+ if ( lastPart is ListValueParsingType . QuoteStart )
457
+ {
458
+ // 引号后紧跟着的值
459
+ thisPartStartIndex = index ;
460
+ lastPart = ListValueParsingType . QuotedValue ;
461
+ continue ;
462
+ }
463
+ if ( lastPart is ListValueParsingType . QuotedValue )
464
+ {
465
+ // 引号中值后的值
466
+ lastPart = ListValueParsingType . QuotedValue ;
467
+ continue ;
468
+ }
469
+ if ( lastPart is ListValueParsingType . QuotedSeparator )
470
+ {
471
+ // 引号中分割符(实际上就是正常值)后的值
472
+ lastPart = ListValueParsingType . QuotedValue ;
473
+ continue ;
474
+ }
475
+ if ( lastPart is ListValueParsingType . QuoteEnd )
476
+ {
477
+ // 引号结束后的值
478
+ throw new CommandLineParseValueException (
479
+ $ "Invalid value format at index [{ index } ]: { optionValue } ") ;
480
+ }
481
+ if ( lastPart is ListValueParsingType . Value )
482
+ {
483
+ // 正常值后的值
484
+ lastPart = ListValueParsingType . Value ;
485
+ continue ;
486
+ }
487
+ if ( lastPart is ListValueParsingType . Separator )
488
+ {
489
+ // 正常分割符后的值
490
+ thisPartStartIndex = index ;
491
+ lastPart = ListValueParsingType . Value ;
492
+ continue ;
493
+ }
494
+ }
495
+
496
+ // 处理最后一个值
497
+ if ( lastPart is ListValueParsingType . Start )
498
+ {
499
+ // 一开始就结束了(字符串里就没有值)
500
+ yield return "" ;
501
+ }
502
+ else if ( lastPart is ListValueParsingType . QuoteStart or ListValueParsingType . QuotedValue or ListValueParsingType . QuotedSeparator )
503
+ {
504
+ // 引号还没结束,字符串就结束了
505
+ throw new CommandLineParseValueException (
506
+ $ "Missing quote end at index [{ optionValue . Length } ]: { optionValue } ") ;
507
+ }
508
+ else if ( lastPart is ListValueParsingType . QuoteEnd )
509
+ {
510
+ // 引号结束后字符串正常结束
511
+ }
512
+ else if ( lastPart is ListValueParsingType . Value )
513
+ {
514
+ // 正常值结束的字符串
515
+ yield return optionValue [ thisPartStartIndex ..] ;
516
+ }
517
+ else if ( lastPart is ListValueParsingType . Separator )
518
+ {
519
+ // 正常分割符后就结束了字符串
520
+ yield return "" ;
521
+ }
522
+ }
523
+ }
524
+ }
525
+
526
+ file enum ListValueParsingType
527
+ {
528
+ /// <summary>
529
+ /// 尚未开始分割。
530
+ /// </summary>
531
+ Start ,
532
+
533
+ /// <summary>
534
+ /// 引号开始。
535
+ /// </summary>
536
+ QuoteStart ,
537
+
538
+ /// <summary>
539
+ /// 引号中的值。
540
+ /// </summary>
541
+ QuotedValue ,
542
+
543
+ /// <summary>
544
+ /// 引号中的分割符。
545
+ /// </summary>
546
+ QuotedSeparator ,
547
+
548
+ /// <summary>
549
+ /// 引号结束。
550
+ /// </summary>
551
+ QuoteEnd ,
552
+
553
+ /// <summary>
554
+ /// 正常值。
555
+ /// </summary>
556
+ Value ,
557
+
558
+ /// <summary>
559
+ /// 正常分割符。
560
+ /// </summary>
561
+ Separator ,
345
562
}
346
563
347
564
internal enum MultiValueHandling
0 commit comments