Refactor SerializationResourceManager to use Dictionary instead of HashTable#8332
Conversation
| _isReaderDirty = true; | ||
| EnsureResData(); | ||
| return _resData.GetEnumerator(); | ||
| return ((IDictionary)_resData).GetEnumerator(); |
There was a problem hiding this comment.
This part was required, which might make the whole thing pointless if there is a performance cost for the cast?
Ultimately it would be nice if these were updated to be properly typed, but that is a breaking change.
There was a problem hiding this comment.
IDictionary is one of the last implemented interfaces, so performance won't be so great.
https://www.thomasclaudiushuber.com/2020/03/05/c-the-order-of-interfaces-is-important-for-casting-performance/
There was a problem hiding this comment.
@JeremyKuhne I'd love your input on this. The move to generics might be a performance regression here.
There was a problem hiding this comment.
Casting is not going to measure in a scenario like this. While there is a difference, it is incredibly small. A few nanoseconds are not going to matter in something that won't run more than a few times.
| } | ||
|
|
||
| return null; | ||
| Dictionary<string, object> ht = GetResourceSet(culture); |
| { | ||
| // This is for backwards compatibility and also for the case when our reader/writer don't support metadata. We must merge the original enumeration data in here or else existing design time properties won't show up. That would be really bad for things like Localizable. | ||
| Hashtable it = GetResourceSet(CultureInfo.InvariantCulture); | ||
| Dictionary<string, object> it = GetResourceSet(CultureInfo.InvariantCulture); |
...omponentModel/Design/Serialization/ResourceCodeDomSerializer.SerializationResourceManager.cs
Outdated
Show resolved
Hide resolved
...omponentModel/Design/Serialization/ResourceCodeDomSerializer.SerializationResourceManager.cs
Outdated
Show resolved
Hide resolved
|
@elachlan, I see partial nullability in these files. There are multiple instances that needs to be declared as nullable. |
@dreddy-work Edit: I've created an issue for it at #8342 |
|
@elachlan , seems some left out causing build failures : src\System.Windows.Forms.Design\src\System\ComponentModel\Design\Serialization\ResourceCodeDomSerializer.SerializationResourceManager.cs(458,40): error CS8632: (NETCORE_ENGINEERING_TELEMETRY=Build) The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. |
| @@ -874,23 +803,23 @@ public string SetValue(IDesignerSerializationManager manager, ExpressionContext | |||
| { | |||
There was a problem hiding this comment.
@dreddy-work The for loop here has a super weird definition. There are two of these types of for loops within this code file. What would you suggest to do here?
There was a problem hiding this comment.
Loop is trying to find unique name that wasn't used yet. We could simplify it to do-while for readability and should be able to remove warning. I do not see any other technical advantages though. Let's convert to do-while?
There was a problem hiding this comment.
I think I can write this into a Dictionary<string, int> and use the baseName as the key. Therefore keeping track of the count. I'll push through once I work out the proper logic.
There was a problem hiding this comment.
@dreddy-work done! Both should be easier to understand now I think.
...omponentModel/Design/Serialization/ResourceCodeDomSerializer.SerializationResourceManager.cs
Outdated
Show resolved
Hide resolved
...omponentModel/Design/Serialization/ResourceCodeDomSerializer.SerializationResourceManager.cs
Show resolved
Hide resolved
...omponentModel/Design/Serialization/ResourceCodeDomSerializer.SerializationResourceManager.cs
Outdated
Show resolved
Hide resolved
| if (resourceSet is not null && resourceSet.TryGetValue(name, out object parentValue)) | ||
| { | ||
| return CompareValue.Different; | ||
| return !parentValue.Equals(value) || parentValue is null ? CompareValue.Different : CompareValue.Same; |
There was a problem hiding this comment.
what if both parentValue and value is null?
There was a problem hiding this comment.
@elachlan , did you run any tests here? This is core for resource serialization and like to do some unit testing performed with this change and record results before we merge it.
There was a problem hiding this comment.
I did not do any manual testing, but did run the Design Unit Tests.
The ordering seemed important here. Because previously it was checking if both were equal before checking for null. Meaning that its designed to allow both to be null for Same to be returned. So I replicated that logic here.
There was a problem hiding this comment.
can you try a simple application with multiple sets of controls and localize the application?
There was a problem hiding this comment.
I have no idea how to do this. You mean as a part of one of the test projects?
There was a problem hiding this comment.
No, by replacing binaries locally on your machine and create .NET 8.0 targeted application. Here are instructions on private testing in case you have not used them before: https://github.com/dotnet/winforms/blob/main/docs/testing.md
There was a problem hiding this comment.
I was playing around with the tests, the code is only hit in SerializationResourceManager when the PrimitiveCodeDomSerializer is serializing a string with a char count > 200. This isn't tested for.
I tried testing this scenario and writing a separate test class for ResourceCodeDomSerializer. Both resulted in exceptions due to either a missing session. If I manually created a session, then the exception would be on SerializationResourceManager.Writer with a missing ResourceWriter service.
If I could work out how to add a writer service in the test, then I can write tests for it.
There was a problem hiding this comment.
good to know that. Logically, change is no-op here. Lets take it in after addressing rest of the comments.
ResourceCodeDomSerializer.SerializationResourceManagerto replace usages ofHashtable.ResXResourceReaderto useDictionaryinstead ofListDictionaryRelated: #8143
Microsoft Reviewers: Open in CodeFlow