-
Notifications
You must be signed in to change notification settings - Fork 417
Expand file tree
/
Copy pathArgument{T}.cs
More file actions
139 lines (125 loc) · 5.11 KB
/
Argument{T}.cs
File metadata and controls
139 lines (125 loc) · 5.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.CommandLine.Parsing;
using System.Diagnostics.CodeAnalysis;
namespace System.CommandLine
{
/// <inheritdoc cref="Argument" />
public class Argument<T> : Argument
{
private Func<ArgumentResult, T?>? _customParser;
private Func<ArgumentResult, T>? _defaultValueFactory;
/// <summary>
/// Initializes a new instance of the Argument class.
/// </summary>
/// <param name="name">The name of the argument. This name can be used to look up the parsed value and is displayed in help.</param>
public Argument(string name) : base(name)
{
}
/// <summary>
/// Gets or sets the delegate to invoke to create the default value.
/// </summary>
/// <remarks>
/// This delegate is invoked when there was no parse input provided for given Argument.
/// The same instance can be set as <see cref="CustomParser"/>. In that case,
/// the delegate is also invoked when an input was provided.
/// </remarks>
public Func<ArgumentResult, T>? DefaultValueFactory
{
get
{
if (_defaultValueFactory is null)
{
if (this is Argument<bool> boolArgument)
{
boolArgument.DefaultValueFactory = _ => false;
}
}
return _defaultValueFactory;
}
set => _defaultValueFactory = value;
}
/// <summary>
/// Gets or sets a custom argument parser.
/// </summary>
/// <remarks>
/// The custom parser is invoked when there was parse input provided for a given Argument.
/// The same instance can be set as <see cref="DefaultValueFactory"/>; in that case,
/// the delegate is also invoked when no input was provided.
/// </remarks>
public Func<ArgumentResult, T?>? CustomParser
{
get => _customParser;
set
{
_customParser = value;
if (value is not null)
{
ConvertArguments = (ArgumentResult argumentResult, out object? parsedValue) =>
{
int errorsBefore = argumentResult.SymbolResultTree.ErrorCount;
var result = value(argumentResult);
if (errorsBefore == argumentResult.SymbolResultTree.ErrorCount)
{
parsedValue = result;
return true;
}
else
{
parsedValue = default(T)!;
return false;
}
};
}
else
{
ConvertArguments = null;
}
}
}
/// <inheritdoc />
public override Type ValueType => typeof(T);
/// <inheritdoc />
public override bool HasDefaultValue => DefaultValueFactory is not null;
internal override object? GetDefaultValue(ArgumentResult argumentResult)
{
if (DefaultValueFactory is null)
{
throw new InvalidOperationException($"Argument \"{Name}\" does not have a default value");
}
return DefaultValueFactory.Invoke(argumentResult);
}
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050", Justification = "https://github.com/dotnet/command-line-api/issues/1638")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2091", Justification = "https://github.com/dotnet/command-line-api/issues/1638")]
internal static T? CreateDefaultValue()
{
if (default(T) is null && typeof(T) != typeof(string))
{
#if NET7_0_OR_GREATER
if (typeof(T).IsSZArray)
#else
if (typeof(T).IsArray && typeof(T).GetArrayRank() == 1)
#endif
{
return (T?)(object)Array.CreateInstance(typeof(T).GetElementType()!, 0);
}
else if (typeof(T).IsConstructedGenericType)
{
var genericTypeDefinition = typeof(T).GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(IEnumerable<>) ||
genericTypeDefinition == typeof(IList<>) ||
genericTypeDefinition == typeof(ICollection<>))
{
return (T?)(object)Array.CreateInstance(typeof(T).GenericTypeArguments[0], 0);
}
if (genericTypeDefinition == typeof(List<>))
{
return Activator.CreateInstance<T>();
}
}
}
return default;
}
}
}