-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
ConfigurationBinder handles ISet<> #68133
Conversation
Tagging subscribers to this area: @dotnet/area-extensions-configuration Issue DetailsFixes #66141
|
src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Outdated
Show resolved
Hide resolved
@SteveDunn could you please resolve the file conflicts? |
a332a69
to
133ee2e
Compare
src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Outdated
Show resolved
Hide resolved
Rebased from main and resolved conflicts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks @SteveDunn
@maryamariyan do you want to have a quick look?
The It might end up that we test for I would like a fix to public interface ICustomCollection<out T> : IEnumerable<T>
{
}
public class MyClassWithCustomCollection
{
public ICustomCollection<string> CustomCollection { get; set; }
}
[Fact]
public void SkipsCustomCollection()
{
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddInMemoryCollection( new Dictionary<string, string>
{
["CustomCollection:0"] = "Yo!",
});
var config = configurationBuilder.Build();
var instance = config.Get<MyClassWithCustomCollection>()!;
Assert.Null(instance.CustomCollection);
} |
Thanks for the suggestion @halter73 . I've fixed the issues mentioned, and the example test case you provided is now included. I also added similar cases for custom dictionaries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upon further review I think we should throw for custom interfaces implementing known collection interface, it just shouldn't be an ArgumentException
thrown when trying to set a property value, it should be an InvalidOperationException
thrown while trying to activate the type like we do for other interfaces.
In my last comment I link to a diff to your PR that has the behavior I want as far as that goes. I didn't go ahead and make all the changes I suggested. For example, we still need to limit sets to strings and enums and write tests for that, but please feel free to cherry-pick these changes.
src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Outdated
Show resolved
Hide resolved
I added the above test and got it passing, but there was no way for this to remain green whilst all others remained green. Do we want to change this behaviour from throwing this exception to just skipping the custom collections (enumerables, sets, dictionaries)? |
This is one of a few of my PRs laying dormant. Is there anything I need to do to progress them? |
No. It's better to stay consistent and throw from all custom collections. That's why I changed all the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the slow turnaround getting back to this. It looks really good. Thanks for sticking with this so long!
I still do want to add a test for a collection without a public Add
method since we nearly regressed this. I asked for this, but it was tucked away in a longer comment.
We should add a test that binds to an explicitly implemented
ICollection<string>
to verify we don't regress this in the future.
@SteveDunn - I think this is the last feedback to address on this PR, and then it can be merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I had 2 more comments.
src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Outdated
Show resolved
Hide resolved
0495612
to
c8ceb43
Compare
src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs
Show resolved
Hide resolved
da7ee3f
to
4f66fda
Compare
I think everything has now been addressed for this. And I also just rebased. |
private static bool IsArrayCompatibleReadOnlyInterface(Type type) | ||
{ | ||
if (!type.IsInterface || !type.IsConstructedGenericType) { return false; } | ||
|
||
Type genericTypeDefinition = type.GetGenericTypeDefinition(); | ||
return genericTypeDefinition == typeof(IEnumerable<>) | ||
|| genericTypeDefinition == typeof(ICollection<>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this fits in with the name of the method: IsArrayCompatibleReadOnlyInterface
- ICollection<>
is not "read-only".
Also, later in the BindInstance
method we are checking for ICollection<>
, does it need to be in both places?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the method is answering the question 'Should the type be treated as immutable?" - e.g. if it's one of these types, then return true
to say not to append to the source, but clone it to a new collection.
I've renamed it as such, although I do think it could be clearer. Do you have any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to check for ICollection<>
in both places?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the second check for ICollection<>
is looking for an Add
method to determine whether to set (add) members of the collection, or whether to bind to properties (line 358).
Do you have any thoughts on how this could be made clearer? To be perfectly honest, I do find this method rather confusing!
src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Outdated
Show resolved
Hide resolved
9252089
to
ca1defe
Compare
No worries at all, you must be busy (if you need an additional member of the team, I'd love to join!) |
The failure in Windows x64 Debug run is unrelated and tracked by #72428 |
Fixes #66141