Skip to content

Commit cf37f40

Browse files
authored
Fix for #1248: Hosting with BindCommandLine throws TargetParameterCountException (#1277)
* fix #1248 * Add TestCase * review comment
1 parent 43f8d11 commit cf37f40

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

src/System.CommandLine.Tests/Binding/ModelBinderTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,20 @@ public void Parse_result_can_be_used_to_modify_an_existing_instance_without_doin
265265
instance.IntOption.Should().Be(123);
266266
}
267267

268+
[Fact]
269+
public void Modify_an_existing_instance_should_keep_all_default_values_if_no_argument_matches_option()
270+
{
271+
var parser = new Parser(new Command("the-command"));
272+
273+
var instance = new ClassWithComplexTypes();
274+
var bindingContext = new BindingContext(parser.Parse("the-command"));
275+
var binder = new ModelBinder(typeof(ClassWithComplexTypes));
276+
277+
binder.UpdateInstance(instance, bindingContext);
278+
279+
instance.Should().BeEquivalentTo(new ClassWithComplexTypes());
280+
}
281+
268282
[Fact]
269283
public void Values_from_options_on_parent_commands_are_bound_by_name_by_default()
270284
{
@@ -475,6 +489,7 @@ public void PropertyExpression_can_be_bound_to_argument()
475489
instance.IntOption.Should().Be(42);
476490
}
477491

492+
478493
[Fact]
479494
public void Option_argument_is_bound_to_longest_constructor()
480495
{

src/System.CommandLine.Tests/Binding/TestModels.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ public class ClassWithMultiLetterSetters
3030
public bool BoolOption { get; set; }
3131
}
3232

33+
public class ClassWithComplexTypes
34+
{
35+
public int IntOption { get; set; }
36+
public string StringOption { get; set; }
37+
public bool BoolOption { get; set; }
38+
public List<ClassWithMultiLetterSetters> ListOptionDefaultNull { get; set; }
39+
public List<ClassWithCtorParameter<string>> ListOptionDefaultEmpty { get; set; } = new ();
40+
}
41+
3342
public class ClassWithListTypePropertiesAndDefaultCtor
3443
{
3544
public List<string> Strings { get; set; }

src/System.CommandLine/Binding/ModelBinder.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -265,23 +265,23 @@ internal static (BoundValue? boundValue, bool usedNonDefault) GetBoundValue(
265265
return (boundValue, true);
266266
}
267267

268-
if (valueDescriptor.HasDefaultValue)
268+
if (includeMissingValues)
269269
{
270-
return (BoundValue.DefaultForValueDescriptor(valueDescriptor), false);
271-
}
270+
if (valueDescriptor.HasDefaultValue)
271+
{
272+
return (BoundValue.DefaultForValueDescriptor(valueDescriptor), false);
273+
}
272274

273-
if (valueDescriptor.ValueType != parentType) // Recursive models aren't allowed
274-
{
275-
var binder = bindingContext.GetModelBinder(valueDescriptor);
276-
var (success, newInstance, usedNonDefaults) = binder.CreateInstanceInternal(bindingContext);
277-
if (success)
275+
if (valueDescriptor.ValueType != parentType) // Recursive models aren't allowed
278276
{
279-
return (new BoundValue(newInstance, valueDescriptor, valueSource), usedNonDefaults);
277+
var binder = bindingContext.GetModelBinder(valueDescriptor);
278+
var (success, newInstance, usedNonDefaults) = binder.CreateInstanceInternal(bindingContext);
279+
if (success)
280+
{
281+
return (new BoundValue(newInstance, valueDescriptor, valueSource), usedNonDefaults);
282+
}
280283
}
281-
}
282284

283-
if (includeMissingValues)
284-
{
285285
if (valueDescriptor is ParameterDescriptor parameterDescriptor && parameterDescriptor.AllowsNull)
286286
{
287287
return (new BoundValue(parameterDescriptor.GetDefaultValue(), valueDescriptor, valueSource), false);

0 commit comments

Comments
 (0)