Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace earlier binding infrastructure #408

Merged
merged 14 commits into from
Feb 20, 2019

Conversation

jonsequitur
Copy link
Contributor

@jonsequitur jonsequitur commented Feb 9, 2019

This is attempt #3 at a generalized model binding infrastructure with lessons learned from the previous two iterations. If we think this is a good approach, this is intended to replace the following types and their related code:

  • TypeBinder
  • MethodBinder
  • ReflectionBinder

This is intended to address the following scenarios in a way that is flexible enough to be leveraged within app models, e.g. DragonFruit:

  • Binding input from various sources (ParseResult, service provider, arbitrary inputs such as environment variables, etc.) to arbitrary types (including constructor parameters, property setters, and handler parameters)
  • Binding in the absence of invocation
  • Easier testing of binding operations

It also shifts the code for building options based on a method signature, which DragonFruit uses, into System.CommandLine.DragonFruit. Some of this may later move under the app model work but as it's highly convention-based, we decided that it does not belong in the core library.

@jonsequitur jonsequitur changed the title [WIP] decompose binding [WIP] decomposed model binding Feb 10, 2019
return GetValues(context, ConstructorDescriptor.ParameterDescriptors);
}

public object CreateInstance(BindingContext context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, consider GetInstance

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain how you think about the distinction here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second look, Create is fine

src/System.CommandLine/Binding/ModelBinder.cs Outdated Show resolved Hide resolved
new SpecificSymbolValueSource(option));
}

public void BindMemberFromCommand<TValue>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean BindMemberFromArgument? How will a tight coupling between commands and arguments here work with multiple arguments? I do not believe people think about commands having values as much as having arguments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore the above because this isn't the place for it, but to clarify the confusion.

Our implementation is at odds with the ways I believe people think about the problem, and reflects an implementation detail. I do not believe people say "What's the value of that command?" Nor "What's the value of the argument on that option?" I think they would say "What's the value of the argument?" or "What's the value of the option?" and that is how Help seems laid out to me. I think this is going to be a rough cognitive load and reflects an implementation detail, and I know I will keep making this mistake whenever I am thinking about the real problem (the CLI).

But this has nothing to do with the problem we are trying to solve today.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does mean bind from the argument. The concern is a good one. I think conceptually "What is the value for this option" is more intuitive but less precise than "What is the value for this option's argument"? And yes, the value for a command will become more ambiguous with #310.


namespace System.CommandLine.Binding
{
public class ModelDescriptor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppModels will need to set just some properties. I think this will be a need for some other cases as well. How would you pass the list of PropertyDescriptors to this class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean set some properties that were not discovered via reflection?

src/System.CommandLine/Binding/SymbolBindingSide.cs Outdated Show resolved Hide resolved

public bool HasDefaultValue => false;

public object GetDefaultValue() => null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

People may be confused by this - properties now appear to have default values. Not sure if we can work with them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't intended to being limited the capabilities of reflection. The intention is to be able to annotate the model descriptor so that, for example, if you know that a given type behaviorally has a default, you can define that in the model.


public bool HasDefaultValue => false;

public object GetDefaultValue() => null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider returning the type default instead of null.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch.

@jonsequitur
Copy link
Contributor Author

@dotnet-bot test Ubuntu16.04 Release

@jonsequitur jonsequitur changed the title [WIP] decomposed model binding replace earlier binding infrastructure Feb 19, 2019
@jonsequitur
Copy link
Contributor Author

@dotnet-bot test Ubuntu16.04 Release

@jonsequitur jonsequitur merged commit c9450cb into dotnet:master Feb 20, 2019
@jonsequitur jonsequitur deleted the decompose-ReflectionBinder branch May 20, 2019 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants