-
-
Notifications
You must be signed in to change notification settings - Fork 269
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
Attribute-based Guards? #74
Comments
Those have to be evaluated somehow externally, I think, much like model validation works in ASP.NET MVC. Guard Clauses as they're used in this project are standalone, self-contained static functions that don't require any kind of wrapper or other plumbing around how they're used or how functions using them are called. If I'm mistaken and there's a way to implement an attribute-based approach that wouldn't force dependencies on how the methods using them were called, I'm open to it. |
This wouldn't be until .NET 5/C#9, but there's an upcoming compiler feature called C# Source Generators. I was hoping we could have a generator that inspects the parameter attributes and emits the guard code (this occurs at compile-time). However, since Source Generators cannot modify existing code by design, FWICT we'd still need a call within the ctor to invoke the gen'd code. The design I came up involves partial methods for the guard code: public partial class MyClass
{
// Partial method declaration (the definition will be generated by the source generator).
// This decl itself could be generated by a Code Fix. The Code Fix would have to ensure to name this method
// uniquely so as to disambiguate it from other methods in the class that may have the same signature.
static partial void Guard(int fooParam);
int _foo;
public MyClass([Positive] int fooParam)
{
Guard(fooParam); // calls the generated partial method
_foo = fooParam;
}
} // MyClass.GuardClauses.cs
// THIS IS GENERATED CODE. DO NOT MODIFY
public partial class MyClass
{
static partial void Guard(int fooParam)
{
Guard.Against.NegativeOrZero(fooParam, "fooParam"); // no need for nameof() as this is gen'd code
}
} Yeah, unfortunately, I think there's too much ceremony because of the fact that source generators can't modify existing source to stick the guards at the beginning of the constructor. Unless there's a better strategy, this necessitates partial classes/methods (that need to avoid signature ambiguity no less). Even if we had an analyzer to detect missing partial methods and their invocations and provide a Code Fix to generate/update them, that adds even more ceremony:
which provides little benefit over the existing approach IMO. The Code Fix in (3) might as well just generate inlined If Source Generators allowed modifying existing code, I think it would be a different story. Leaving this here for now in case someone sees something I missed. |
Have you considered an approach using attributes (maybe DataAnnotations) in the method's parameter lists, analogous to this capability in Java EE? I searched issues and PRs for a related discussion but came up empty.
The text was updated successfully, but these errors were encountered: