-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
API Proposal: Add ConfigurationBinder.Bind<T> overloads #43930
Comments
Tagging subscribers to this area: @maryamariyan |
I believe given the concrete class: public class Person
{
public string Name { get; set; }
} the two overloads below in combination // The APIs proposed in this issue. So when source gen is not enabled, config binding would remain linker friendly
public static class ConfigurationBinder
{
public static void Bind<T>(this IConfiguration configuration, T instance, Action<BinderOptions> configureOptions)
=> configuration.Bind((object)instance, configureOptions);
...
}
// source generated code for the concrete types, with compiler ideally picking this overload rather than ambiguous error
public static class PersonConfigurationExensions
{
public static void Bind<Person>(this IConfiguration configuration, Person instance, Action<BinderOptions> configureOptions)
=> configuration.Bind((object)instance, configureOptions);
...
} would cause ambiguous compile error:
@davidfowl would it be enough for configuration binding to be linker friendly only when source generation is enabled? If yes, then perhaps we could skip these proposed API additions (additions drafted here) and source gen drafted here. |
This works for me: // The APIs proposed in this issue. So when source gen is not enabled, config binding would remain linker friendly
public static class ConfigurationBinder
{
public static void Bind<T>(this IConfiguration configuration, T instance, Action<BinderOptions> configureOptions)
=> configuration.Bind((object)instance, configureOptions);
}
// source generated code for the concrete types, with compiler ideally picking this overload rather than ambiguous error
public static class PersonConfigurationExensions
{
public static void Bind<T>(this IConfiguration configuration, T instance, Action<BinderOptions> configureOptions) where T : Person
{
// Source generated implementation
}
} |
Thanks, I missed adding the where clause in the code blob above, that is needed. What I noticed is that we'd still get the ambiguous error even if the two APIs are in two different namespaces and both are added as using statements. Minimal repro here |
Yes this should be fine assuming all of the overloads today are non-generic. |
UPDATE: Note on trimming:As described in the issue here, we'd still need the three APIs above for enabling linker friendly attributes. public class ComplexOptions
{
public int Integer { get; set; }
public NestedOptions Nested { get; set; }
}
public class NestedOptions
{
public FurtherNestingOptions FurtherNesting { get; set; }
} Where the linker needs to understand not to trim FurtherNestingOptions in this case. Note on source generationBut seems like for the source gen code, we don't really need to conflict with the above three APIs. Instead we could generate something like: public static void Bind(this IConfiguration configuration, Person instance, Action<BinderOptions> configureOptions) This way we can avoid the ambiguous match compile error. |
See dotnet/linker#1087 for more information on the issue with the linker in this area. |
This is the case with JsonDeserialize as well. We just need to be able to annotate things (this should have the same annotations as JSON even if they are not fully capable today) since today we can't even do that because of the object overload. |
If this API is approved, consider having the new overloads annotated where T : class, or if this is not practical, their implementations should fail if T is a value type. Passing a value type T will end up making a copy, so binding the configuration to that instance will essentially be an expensive no-op, and the user probably didn't intend for this to happen. |
namespace Microsoft.Extensions.Configuration
{
public partial class ConfigurationBinder
{
public static void Bind<T>(this IConfiguration configuration, string key, T instance);
public static void Bind<T>(this IConfiguration configuration, T instance);
public static void Bind<T>(this IConfiguration configuration, T instance, Action<BinderOptions> configureOptions);
}
} |
@GrabYourPitchforks great observation! |
Background and Motivation
We need to enable annotating liker friendly attributes to be applied to the generic argument to preserve things and to allow source generators to replace the implementation of this method by adding generic overloads specialized to a specific T.
Proposed API
Usage Examples
Risks
None.
PS: These will basically win over the non-generic overloads when the instance isn't typed as object.
cc @jaredpar to check my compiler math.
The text was updated successfully, but these errors were encountered: