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

Fix issue when adding a new complex value to a generic dictionary #29

Merged
merged 4 commits into from
May 30, 2024

Conversation

rmja
Copy link
Contributor

@rmja rmja commented May 30, 2024

This pr fixes an issue that it shown by the added test where it is not possible to add a complex object to a typed dictionary.

The fix prefers to use the IDictionary<TKey, TValue> proxy over the IDictionary proxy as e.g. Dictionary<TKey, TValue> implements both.

@rmja
Copy link
Contributor Author

rmja commented May 30, 2024

One thing that I would like to change but that could be breaking is to not find the PropertyType from an instance in the dictionary:

https://github.com/rmja/SystemTextJsonPatch/blob/generic-dictionary/SystemTextJsonPatch/Internal/Proxies/DictionaryTypedPropertyProxy.cs#L44-L56

public Type PropertyType => typeof(TValue);
{
	get
	{
		_dictionary.TryGetValue(_propertyName, out var val);
		if (val == null)
		{
			return typeof(TValue);
		}

		return val.GetType();
	}
}

This should instead be public Type PropertyType => typeof(TValue); to allow for the case where TValue may be a base type to which as custom converter is attached. By using the type from the current instance as is the current approach, this limits the ability to replace an instance of one derived type with another.

@Havunen
Copy link
Owner

Havunen commented May 30, 2024

Hi,

Thanks for the PR.

This should instead be public Type PropertyType => typeof(TValue); to allow for the case where TValue may be a base type to which as custom converter is attached. By using the type from the current instance as is the current approach, this limits the ability to replace an instance of one derived type with another.

That type is not considered public, so it should be safe to change as long as it works as expected

@rmja
Copy link
Contributor Author

rmja commented May 30, 2024

Hi,

Thanks for the PR.

This should instead be public Type PropertyType => typeof(TValue); to allow for the case where TValue may be a base type to which as custom converter is attached. By using the type from the current instance as is the current approach, this limits the ability to replace an instance of one derived type with another.

That type is not considered public, so it should be safe to change as long as it works as expected

The compatibility problem if we chose to have Type PropertyType => typeof(TValue) is the following:

Old behavior:
If we update an entry in the dictionary then we try and convert to the entry value instance type. Consider for example Dictionary<string, AnimalBase> where we could possible convert to typeof(Dog) if a dog entry exists, where Dog: AnimalBase.

The result, we try and convert to typeof(Dog).

New behavor:
We always try and convert to typeof(AnimalBase).

The problem with the old behavior is if we want to replace the entry to some other type, e.g. Dog -> Cat. That would only be possible if we convert to the base type (Type PropertyType => typeof(TValue)). One can argue that the current behavior is a bug, in which case, if we decide to change it, is not a breaking change:)

@rmja
Copy link
Contributor Author

rmja commented May 30, 2024

I have included the Type PropertyType => typeof(TValue) change and added a corresponding test. And, the ctor is internal again.

Copy link
Owner

@Havunen Havunen left a comment

Choose a reason for hiding this comment

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

LGTM! Thank you for the contribution!

@Havunen Havunen merged commit e00dfc2 into Havunen:main May 30, 2024
3 checks passed
@Havunen
Copy link
Owner

Havunen commented May 30, 2024

This is now available in Nuget v3.2.0

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