Skip to content

Commit 954c1c6

Browse files
committed
Extended the automatic type conversion
There is no need for a CastAs Attribute anymore, so I removed it. The Parser now automatically converts the argument to the field type.
1 parent 3dd65c8 commit 954c1c6

6 files changed

Lines changed: 91 additions & 105 deletions

File tree

src/libArgument/libArgument.Tests/Test.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,12 @@ public class Options {
1818
public bool Log;
1919

2020
[Argument ("n", "num")]
21-
[CastAs (CastingType.Int32)]
2221
public int ANumber;
2322

2423
[Argument ("f", "float")]
25-
[CastAs (CastingType.Float)]
2624
public float AFloat;
2725

2826
[Argument ("b", "bool")]
29-
[CastAs (CastingType.Boolean)]
3027
public bool ABool;
3128
}
3229

src/libArgument/libArgument.userprefs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<Properties StartupItem="libArgument.Tests\libArgument.Tests.csproj">
22
<MonoDevelop.Ide.Workspace ActiveConfiguration="Release" />
3-
<MonoDevelop.Ide.Workbench ActiveDocument="libArgument\Attributes\CastAs.cs">
3+
<MonoDevelop.Ide.Workbench ActiveDocument="libArgument\ArgumentParser.cs">
44
<Files>
5-
<File FileName="libArgument\ArgumentParser.cs" Line="1" Column="1" />
5+
<File FileName="libArgument\ArgumentParser.cs" Line="123" Column="123" />
66
<File FileName="libArgument\Attributes\CastAs.cs" Line="3" Column="3" />
77
</Files>
88
</MonoDevelop.Ide.Workbench>

src/libArgument/libArgument/ArgumentParser.cs

Lines changed: 89 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,97 +4,122 @@
44
using System.Linq;
55
using System.Reflection;
66
using Codeaddicts.libArgument.Attributes;
7+
using System.ComponentModel;
78

89
namespace Codeaddicts.libArgument
910
{
11+
/// <summary>
12+
/// Codeaddicts ArgumentParser
13+
/// </summary>
1014
public static class ArgumentParser
1115
{
16+
/// <summary>
17+
/// Parses the specified arguments.
18+
/// </summary>
19+
/// <param name="args">Arguments.</param>
20+
/// <typeparam name="T">The class that contains the options.</typeparam>
1221
public static T Parse<T> (string[] args) where T : class, new()
1322
{
23+
// Instantiate the class that contains the options
1424
T options = new T ();
25+
26+
// Create a new List<string> and fill it with the arguments
1527
var list = new List<string> (args);
28+
29+
// Get all public fields from the class instance
1630
var fields = typeof (T).GetFields (BindingFlags.Instance | BindingFlags.Public);
31+
32+
// Iterate over all fields
1733
foreach (var item in fields)
34+
35+
// Parse the current field
1836
ParseField<T> (options, list, item.Name);
37+
38+
// Return the generated class instance
1939
return options;
2040
}
2141

42+
/// <summary>
43+
/// Generates and prints the argument doc.
44+
/// </summary>
45+
/// <typeparam name="T">The 1st type parameter.</typeparam>
46+
static void PrintHelp<T> () where T : class, new()
47+
{
48+
// Not ready yet.
49+
}
50+
51+
/// <summary>
52+
/// Parses the field.
53+
/// </summary>
54+
/// <param name="options">Options.</param>
55+
/// <param name="args">Arguments.</param>
56+
/// <param name="name">Name.</param>
57+
/// <typeparam name="T">The 1st type parameter.</typeparam>
2258
static void ParseField<T> (T options, List<string> args, string name) where T : class, new()
2359
{
60+
// Get field
2461
var field = typeof(T).GetField (name);
62+
63+
// Get attributes
2564
var attributes = field.GetCustomAttributes (true);
26-
var cast = attributes.FirstOrDefault (attrib => attrib as CastAs != null) as CastAs ?? new CastAs (CastingType.String);
65+
66+
// Iterate over the attributes
2767
foreach (var attrib in attributes) {
28-
if (attrib as Switch != null && (args.Contains ((attrib as Switch).FriendlyShort) || args.Contains ((attrib as Switch).FriendlyFull))) {
29-
field.SetValue (options, true);
30-
return;
68+
69+
// Check if the current attribute is a Switch attribute
70+
var @switch = attrib as Switch;
71+
if (@switch != null) {
72+
73+
// Check if the current attribute contains a valid parameter name
74+
if (args.Contains (@switch.FriendlyShort) || args.Contains (@switch.FriendlyFull)) {
75+
76+
// Set value and return
77+
field.SetValue (options, true);
78+
return;
79+
}
3180
}
81+
82+
// Check if the current attribute is an Argument attribute
3283
if (attrib as Argument == null)
84+
85+
// Skip this iteration
3386
continue;
87+
88+
// Get the current attribute
3489
var attribute = attrib as Argument;
90+
91+
// Check if the arguments contain any of the valid parameter names
3592
if (!(args.Contains (attribute.FriendlyShort) || args.Contains (attribute.FriendlyFull)))
93+
94+
// Skip this iteration
3695
continue;
37-
var str = args.Contains (attribute.FriendlyShort) ? attribute.FriendlyShort : attribute.FriendlyFull;
38-
var index = args.IndexOf (str) + 1;
39-
var indexInRange = index <= args.Count - 1;
40-
if (cast.Type != CastingType.Boolean && !indexInRange)
41-
throw new ArgumentOutOfRangeException (string.Format ("Parameter of argument {0} out of range.", str));
42-
switch (cast.Type) {
43-
case CastingType.String:
44-
field.SetValue (options, args [index]);
45-
return;
46-
case CastingType.Boolean:
47-
bool bool_result;
48-
if (!Boolean.TryParse (args [index], out bool_result))
49-
throw new InvalidCastException (string.Format ("Can't cast parameter of argument {0} to Boolean.", str));
50-
field.SetValue (options, bool_result);
51-
return;
52-
case CastingType.Object:
53-
field.SetValue (options, args [index]);
54-
return;
55-
case CastingType.Int32:
56-
int int32_result;
57-
if (!Int32.TryParse (args [index], out int32_result))
58-
throw new InvalidCastException (string.Format ("Can't cast parameter of argument {0} to Int32.", str));
59-
field.SetValue (options, int32_result);
60-
return;
61-
case CastingType.Int64:
62-
long int64_result;
63-
if (!Int64.TryParse (args [index], out int64_result))
64-
throw new InvalidCastException (string.Format ("Can't cast parameter of argument {0} to Int64.", str));
65-
field.SetValue (options, int64_result);
66-
return;
67-
case CastingType.UInt32:
68-
uint uint32_result;
69-
if (!UInt32.TryParse (args [index], out uint32_result))
70-
throw new InvalidCastException (string.Format ("Can't cast parameter of argument {0} to UInt32.", str));
71-
field.SetValue (options, uint32_result);
72-
return;
73-
case CastingType.UInt64:
74-
ulong uint64_result;
75-
if (!UInt64.TryParse (args [index], out uint64_result))
76-
throw new InvalidCastException (string.Format ("Can't cast parameter of argument {0} to UInt64.", str));
77-
field.SetValue (options, uint64_result);
78-
return;
79-
case CastingType.Long:
80-
long long_result;
81-
if (!long.TryParse (args [index], out long_result))
82-
throw new InvalidCastException (string.Format ("Can't cast parameter of argument {0} to long.", str));
83-
field.SetValue (options, long_result);
84-
return;
85-
case CastingType.ULong:
86-
ulong ulong_result;
87-
if (!ulong.TryParse (args [index], out ulong_result))
88-
throw new InvalidCastException (string.Format ("Can't cast parameter of argument {0} to ulong.", str));
89-
field.SetValue (options, ulong_result);
90-
return;
91-
case CastingType.Float:
92-
float float_result;
93-
if (!float.TryParse (args [index], NumberStyles.Float, CultureInfo.InvariantCulture, out float_result))
94-
throw new InvalidCastException (string.Format ("Can't cast parameter of argument {0} to float.", str));
95-
field.SetValue (options, float_result);
96-
return;
96+
97+
// Get the parameter name
98+
var paramname = args.Contains (attribute.FriendlyShort) ? attribute.FriendlyShort : attribute.FriendlyFull;
99+
100+
// Get the type of the field
101+
var type = field.FieldType;
102+
103+
// Get the index of the current value
104+
var index = args.IndexOf (paramname) + 1;
105+
106+
// Check if the index is in the range of our parameter count
107+
var indexInRange = index < args.Count;
108+
109+
// Check if the index is in range of our parameter count
110+
if (!indexInRange)
111+
throw new ArgumentOutOfRangeException (string.Format ("Parameter of argument {0} is out of range.", paramname));
112+
113+
// Cast the string to the type of the field
114+
object value;
115+
try {
116+
value = TypeDescriptor.GetConverter (type).ConvertFromInvariantString (args [index]);
117+
} catch {
118+
throw new Exception (string.Format ("Cannot convert <string> to <{0}>.", type));
97119
}
120+
121+
// Set the value of the field and return
122+
field.SetValue (options, value);
98123
}
99124
}
100125
}

src/libArgument/libArgument/Attributes/CastAs.cs

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/libArgument/libArgument/Attributes/CastingType.cs

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/libArgument/libArgument/libArgument.csproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535
<Compile Include="ArgumentParser.cs" />
3636
<Compile Include="Attributes\Switch.cs" />
3737
<Compile Include="Attributes\Argument.cs" />
38-
<Compile Include="Attributes\CastAs.cs" />
39-
<Compile Include="Attributes\CastingType.cs" />
4038
</ItemGroup>
4139
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
4240
<ItemGroup>

0 commit comments

Comments
 (0)