Skip to content

Commit 3c4e726

Browse files
committed
Fix issue# 339 of custom struct (#588)
1 parent dcfbd8d commit 3c4e726

File tree

4 files changed

+102
-1
lines changed

4 files changed

+102
-1
lines changed

src/CommandLine/Core/ReflectionExtensions.cs

+8
Original file line numberDiff line numberDiff line change
@@ -209,5 +209,13 @@ public static bool IsPrimitiveEx(this Type type)
209209
}.Contains(type)
210210
|| Convert.GetTypeCode(type) != TypeCode.Object;
211211
}
212+
213+
public static bool IsCustomStruct(this Type type)
214+
{
215+
var isStruct = type.GetTypeInfo().IsValueType && !type.GetTypeInfo().IsPrimitive && !type.GetTypeInfo().IsEnum && type != typeof(Guid);
216+
if (!isStruct) return false;
217+
var ctor = type.GetTypeInfo().GetConstructor(new[] { typeof(string) });
218+
return ctor != null;
219+
}
212220
}
213221
}

src/CommandLine/Core/TypeConverter.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ private static Result<object, Exception> ChangeTypeScalarImpl(string value, Type
111111
}
112112
};
113113

114+
if (conversionType.IsCustomStruct()) return Result.Try(makeType);
114115
return Result.Try(
115116
conversionType.IsPrimitiveEx() || ReflectionHelper.IsFSharpOptionType(conversionType)
116117
? changeType
@@ -135,4 +136,4 @@ private static object ToEnum(this string value, Type conversionType, bool ignore
135136
throw new FormatException();
136137
}
137138
}
138-
}
139+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
2+
3+
using System;
4+
5+
namespace CommandLine.Tests.Fakes
6+
{
7+
public class CustomStructOptions
8+
{
9+
[Option('c', "custom", HelpText = "Custom Type")]
10+
public CustomStruct Custom { get; set; }
11+
}
12+
13+
public struct CustomStruct
14+
{
15+
public string Input { get; set; }
16+
public string Server { get; set; }
17+
public int Port { get; set; }
18+
public CustomStruct(string url)
19+
{
20+
Input = url;
21+
Server = "";
22+
Port = 80;
23+
var data = url.Split(':');
24+
if (data.Length == 2)
25+
{
26+
Server = data[0];
27+
Port = Convert.ToInt32(data[1]);
28+
}
29+
}
30+
}
31+
32+
public class CustomClassOptions
33+
{
34+
[Option('c', "custom", HelpText = "Custom Type")]
35+
public CustomClass Custom { get; set; }
36+
}
37+
38+
public class CustomClass
39+
{
40+
public string Input { get; set; }
41+
public string Server { get; set; }
42+
public int Port { get; set; }
43+
public CustomClass(string url)
44+
{
45+
Input = url;
46+
Server = "";
47+
Port = 80;
48+
var data = url.Split(':');
49+
if (data.Length == 2)
50+
{
51+
Server = data[0];
52+
Port = Convert.ToInt32(data[1]);
53+
}
54+
}
55+
}
56+
}

tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs

+36
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,42 @@ public void Options_In_Group_Do_Not_Allow_Mutually_Exclusive_Set()
12211221
errors.Should().BeEquivalentTo(expectedResult);
12221222
}
12231223

1224+
#region custom types
1225+
1226+
1227+
[Theory]
1228+
[InlineData(new[] { "-c", "localhost:8080" }, "localhost", 8080)]
1229+
public void Parse_custom_struct_type(string[] arguments, string expectedServer, int expectedPort)
1230+
{
1231+
//Arrange
1232+
1233+
// Act
1234+
var result = InvokeBuild<CustomStructOptions>(arguments);
1235+
1236+
// Assert
1237+
var customValue = ((Parsed<CustomStructOptions>)result).Value.Custom;
1238+
customValue.Server.Should().Be(expectedServer);
1239+
customValue.Port.Should().Be(expectedPort);
1240+
customValue.Input.Should().Be(arguments[1]);
1241+
}
1242+
1243+
[Theory]
1244+
[InlineData(new[] { "-c", "localhost:8080" }, "localhost", 8080)]
1245+
public void Parse_custom_class_type(string[] arguments, string expectedServer, int expectedPort)
1246+
{
1247+
//Arrange
1248+
1249+
// Act
1250+
var result = InvokeBuild<CustomClassOptions>(arguments);
1251+
1252+
// Assert
1253+
var customValue = ((Parsed<CustomClassOptions>)result).Value.Custom;
1254+
customValue.Server.Should().Be(expectedServer);
1255+
customValue.Port.Should().Be(expectedPort);
1256+
customValue.Input.Should().Be(arguments[1]);
1257+
}
1258+
1259+
#endregion
12241260
private class ValueWithNoSetterOptions
12251261
{
12261262
[Value(0, MetaName = "Test", Default = 0)]

0 commit comments

Comments
 (0)