Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Support IDictionary<string,TValue> without IDictionaryEnumerator#41903

Merged
steveharter merged 3 commits into
dotnet:masterfrom
steveharter:DictionaryOfT
Oct 22, 2019
Merged

Support IDictionary<string,TValue> without IDictionaryEnumerator#41903
steveharter merged 3 commits into
dotnet:masterfrom
steveharter:DictionaryOfT

Conversation

@steveharter

Copy link
Copy Markdown
Contributor

Fixes https://github.com/dotnet/corefx/issues/41329. I was unable to verify against the linked repro because SqlMapper.DapperRow and .DapperTable are not public members.

Originally this was going to also have a perf fix that removes boxing of the dictionary enumerator as well, but I decided to just have the raw fix that enables IDictionary<TKey, TValue>-derived dictionaries to work properly.

This may have some conflicts with #41482

This is expected to be ported to 3.1.

@steveharter steveharter added this to the 5.0 milestone Oct 18, 2019
@steveharter steveharter self-assigned this Oct 18, 2019
@ahsonkhan

Copy link
Copy Markdown

Can you test and see if it also fixes ModelStateDictionary https://github.com/dotnet/corefx/issues/41399

@layomia layomia left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some comments, pending the sync with master.

Comment thread src/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs Outdated
Comment thread src/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs Outdated
ClassType == ClassType.IDictionaryConstructible);

if (writeStackFrame.CollectionEnumerator is IDictionaryEnumerator iDictionaryEnumerator)
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would it be beneficial to perform this check at the calling site of this method, since we don't need the generic support? That way we don't need to call into the JsonPropertyInfo.

On the other hand, would performing the generic check done in DictionaryValuePropertyPolicy.GetDictionaryKeyAndValueFromGenericDictionary() first (before checking for IDictionaryEnumerator) have a perf benefit (by avoiding boxing) for types whose .GetEnumerator() method implements both IDictionaryEnumerator and IEnumerator<KeyValuePair<,>> (e.g. Dictionary<,>)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is called from more than one location, so keeping it in the helper method is a bit cleaner.

On the generic check, I think it is better to check for non-generic first in this case as the generic check will unnecessary create a "policy property" (which is expensive) in the non-generic cases.

Also, as a separate PR I'm working on avoid boxing in general for this case for perf...


if (elementClassInfo.ClassType == ClassType.Value)
{
elementClassInfo.PolicyProperty.WriteDictionary(ref state, writer);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since we might have the value here from the polymorphic check above, should we have logic here to see if we do, and just write the key and value here, skipping all the logic that will happen in (and on the path to) WriteDictionary<TProperty>() below?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes passing the key\value down is possible here but requires a new helper method that would essentially copy most of the code\flow in WriteDictionary in order to bounce from non-generic to generic. Plus add associated tests.

Since the original code also obtained the key and value before calling WriteDictionary, which didn't change here, I'll include this optimization in the other PR mentioned earlier for boxing. Thanks

@steveharter

Copy link
Copy Markdown
Contributor Author

Can you test and see if it also fixes ModelStateDictionary #41399

I replied to that PR for a repro. I couldn't repro the original issue, but based on the exception it appears it would be fixed by this PR.

@ahsonkhan

Copy link
Copy Markdown

I was unable to verify against the linked repro because SqlMapper.DapperRow and .DapperTable are not public members.

@steveharter - can you use this commit to verify SqlMapper.DapperRow works now?

ahsonkhan@085ca53

picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Support IDictionary<string,TValue> without IDictionaryEnumerator

Commit migrated from dotnet/corefx@d3c2984
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Serializer errors for dictionaries that don't implement IDictionary

3 participants