-
Notifications
You must be signed in to change notification settings - Fork 351
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
Isolate scoped settings in default OData services #3071
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,15 +55,15 @@ public static IServiceCollection AddDefaultODataServices(this IServiceCollection | |
// Finally, register configurable settings. | ||
var readerSettings = new ODataMessageReaderSettings(odataVersion); | ||
configureReaderAction?.Invoke(readerSettings); | ||
services.AddScoped(sp => readerSettings); | ||
services.AddScoped(sp => readerSettings.Clone()); | ||
|
||
var writerSettings = new ODataMessageWriterSettings(odataVersion); | ||
configureWriterAction?.Invoke(writerSettings); | ||
services.AddScoped(sp => writerSettings); | ||
services.AddScoped(sp => writerSettings.Clone()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @syprieur That's a very good question, apparently it does :( The settings from the see:
which calls: internal static ODataMessageWriterSettings CreateWriterSettings(
IServiceProvider container,
ODataMessageWriterSettings other)
{
ODataMessageWriterSettings writerSettings;
if (container == null)
{
writerSettings = new ODataMessageWriterSettings();
}
else
{
// we get the scoped settings
writerSettings = container.GetRequiredService<ODataMessageWriterSettings>();
}
if (other != null)
{
// then overwrite the scoped service based on the settings passed to the writer
writerSettings.CopyFrom(other);
}
return writerSettings;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That explains the observed bug and confirms the hypothesis: the same settings instance is indeed re-used and updated concurrently. |
||
|
||
var parserSettings = new ODataUriParserSettings(); | ||
configureUriParserAction?.Invoke(parserSettings); | ||
services.AddScoped(sp => parserSettings); | ||
services.AddScoped(sp => parserSettings.Clone()); | ||
|
||
return services; | ||
} | ||
|
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.
question: Would there be an issue if we called configure reader action multiple times e.g. if we used a delegate instead of the cloned instance?
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.
Are you referring to this approach:
If so, I considered it (and mentioned it in the attached issue). The reason I opted for cloning instead of that approach is because we can't predict the cost of the delegate since it's user defined, for all we know it could be reading from a file or database. On the other hand, since we control the implementation of the
Clone()
method, we can make better assumptions about it cost and we can optimize if it becomes a hotspot, so I think it's safer to err on the side of callingClone()
multiple times rather than calling the opaque user-defined delegate multiple times.