-
Notifications
You must be signed in to change notification settings - Fork 0
Suggested additions to the repo #1
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
base: review
Are you sure you want to change the base?
Changes from 1 commit
ee99648
bda1bab
c7006c0
1ed8d2a
7d68406
0a2e37d
27ba6ae
540c4c8
43cc1a7
9f16f46
7cc6405
35fdbf0
b8d8e06
33fee89
c817926
88a702a
c8be315
eb0ead3
4d5100a
c8bc9b4
17d1516
f6d9a58
0a00436
79739bd
a4ef649
ccf4f5d
9cceef9
513d788
d99137e
90c7407
a08ffe4
8338be0
76aa23e
1daeabc
fec01b1
dbf653b
b0879e6
043f638
75d7a72
c577e8c
4f89dbd
373a246
e9920e5
78b35ed
cca4516
d630c93
66e91a0
2fee58b
6f69f3b
603ea68
8b4cc3f
60fb66a
92859d5
26255e5
d2465cf
d42c9f9
393816e
4f7e2d7
404d869
ba32a27
dff60aa
7abeed8
015bbe3
c407387
1e1bb8d
d399c5f
b6ad262
aa10f43
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 |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Common Tasks: Validating String Length | ||
|
||
Inevitably almost every developer will be faced with the necessity to validate the length of a string prior to doing something with it, an obvious case in point would be specifying criteria for a password. | ||
|
||
At this point it's not uncommon for new or relatively inexperienced developers to create a simple checking method to satisfy the immediate requirement. | ||
|
||
```c# | ||
bool ValidateString(string input) | ||
{ | ||
return input.length < 10 && input.length > 16; | ||
} | ||
``` | ||
|
||
If the requirement was that the string be no less than 10 characters in length and no more than 16 then undeniably it will produce a result. If at some point further on in the program another similar check is required then it's very easy to see how this might be copied and pasted with a a couple of alterations to match the next requirement. | ||
|
||
|
||
Using Metalama this task can be easily solved, as it has a number of pre-made contracts for just this type of scenario. | ||
|
||
You could write code as follows (using a simple console application as an example); | ||
|
||
```c# | ||
using Metalama.Patterns.Contracts; | ||
|
||
namespace CommonTasks | ||
{ | ||
internal class Program | ||
{ | ||
|
||
[StringLength(10, 16)] | ||
private static string? password; | ||
|
||
static void Main(string[] args) | ||
{ | ||
try | ||
{ | ||
Console.WriteLine("Enter your Password: "); | ||
|
||
password = Console.ReadLine(); | ||
Console.WriteLine("Your password meets the basic length requirement."); | ||
} catch(ArgumentException ex) | ||
{ | ||
Console.WriteLine(ex.Message); | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Metalama's StringLength aspect takes as parameters either a maximum, or a minimum and maximum length and in the event of a validation failure throws a System.ArgumentException. | ||
|
||
At the point of compilation it adds the necessary logic into your code. | ||
|
||
```c# | ||
using Metalama.Patterns.Contracts; | ||
|
||
namespace CommonTasks | ||
{ | ||
internal class Program | ||
{ | ||
|
||
|
||
private static string? _password1; | ||
|
||
|
||
[StringLength(10, 16)] | ||
private static string? password | ||
{ | ||
get | ||
{ | ||
return Program._password1; | ||
|
||
|
||
} | ||
set | ||
{ | ||
if (value != null && (value!.Length < 10 || value.Length > 16)) | ||
{ | ||
throw new ArgumentException($"The 'password' property must be a string with length between {10} and {16}.", "value"); | ||
} | ||
Program._password1 = value; | ||
|
||
|
||
} | ||
} | ||
static void Main(string[] args) | ||
{ | ||
try | ||
{ | ||
Console.WriteLine("Enter your Password: "); | ||
password = Console.ReadLine(); | ||
Console.WriteLine("Your password meets the basic length requirement."); | ||
} | ||
catch (ArgumentException ex) | ||
{ | ||
Console.WriteLine(ex.Message); | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
The benefit of using Metalama to handle such tasks is that they are handled consistently whilst your own code remains concise, easy to read and comprehend. | ||
|
||
|
||
<br> | ||
|
||
|
||
If you'd like to know more about Metalama in general then visit our [website](https://www.postsharp.net/metalama). | ||
|
||
You can learn more about Metalama contracts [here](https://doc.postsharp.net/metalama/patterns/contracts). | ||
|
||
Why not join us on [Slack](https://www.postsharp.net/slack) where you can keep up with what's new and get answers to any technical questions that you might have. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,103 @@ | ||||||
# Common Tasks: Meeting Requirements | ||||||
|
# Common Tasks: Meeting Requirements | |
# Common Tasks: Verifying required parameters and fields |
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.
That makes sense.
Outdated
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.
It would be good here to talk about [NotNull]
and about nullable reference types in C# and how we can use a fabric method. See https://doc.postsharp.net/metalama/patterns/contracts/enforcing-non-nullability.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Common Tasks: INotifyPropertyChanged | ||
|
||
|
||
We have come to expect application user interfaces to respond almost instantaneously to data that we input into them. This has been made possible by UI's that are built around data bound controls in architecture that implements patterns such as MVVM (Model, View, ViewModel). | ||
|
||
In simple language this works because the UI is able to update when properties in the underlying data models change and in so doing raise the PropertyChanged event. This logic is encapsulated in the INotifyPropertyChanged interface. This pattern has been widely adopted because one of the major benefits that it provides is the ability to reuse data models with different Different views. | ||
|
||
There is however one very notable drawback to using this interface. It requires a great deal of repetitive boiler plate code and that code is not produced automatically so it's possible to omit parts of it unintentionally. | ||
|
||
Dot Net already has an INotifyPropertyChanged Interface so why not just use that. The drawback to that approach is illustrated below. | ||
|
||
<br> | ||
|
||
 | ||
|
||
<br> | ||
|
||
The standard Visual Studio intellisense for this barely does anything. There is still a need to adjust the properties so that they actually raise the event and the event itself needs to be handled. | ||
|
||
If Metalama is used to implement INotifyPropertyChanged then all of the additional code required to make this work will be taken care of. It will be necessary to create an aspect to do this but fortunately there is a great example of such an aspect in the [Metalama Documentation](https://doc.postsharp.net/metalama/examples/notifypropertychanged). | ||
|
||
```c# | ||
using Metalama.Framework.Aspects; | ||
using Metalama.Framework.Code; | ||
using System.ComponentModel; | ||
|
||
namespace CommonTasks.NotifyPropertyChanged | ||
{ | ||
[Inheritable] | ||
internal class NotifyPropertyChangedAttribute : TypeAspect | ||
{ | ||
public override void BuildAspect(IAspectBuilder<INamedType> builder) | ||
{ | ||
builder.Advice.ImplementInterface(builder.Target, typeof(INotifyPropertyChanged), OverrideStrategy.Ignore); | ||
|
||
foreach (var property in builder.Target.Properties.Where(p => | ||
!p.IsAbstract && p.Writeability == Writeability.All)) | ||
{ | ||
builder.Advice.OverrideAccessors(property, null, nameof(this.OverridePropertySetter)); | ||
} | ||
} | ||
|
||
[InterfaceMember] | ||
public event PropertyChangedEventHandler? PropertyChanged; | ||
|
||
[Introduce(WhenExists = OverrideStrategy.Ignore)] | ||
protected void OnPropertyChanged(string name) => | ||
this.PropertyChanged?.Invoke(meta.This, new PropertyChangedEventArgs(name)); | ||
|
||
[Template] | ||
private dynamic OverridePropertySetter(dynamic value) | ||
{ | ||
if (value != meta.Target.Property.Value) | ||
{ | ||
meta.Proceed(); | ||
this.OnPropertyChanged(meta.Target.Property.Name); | ||
} | ||
|
||
return value; | ||
} | ||
} | ||
} | ||
``` | ||
|
||
<br> | ||
|
||
If you read through the code you should be able to see that it implements the INotifyPropertyChanged interface. Having done that it loops through the properties amending their setters where required to raise the the property changed event and finally it correctly implements the INotifyPropertyChanged interface. With the aspect added to your project The INotifyPropertyChanged implementation is made much simpler. | ||
|
||
<br> | ||
|
||
 | ||
|
||
<br> | ||
|
||
In what was an admittedly small and contrived sample class Metalama successfully implemented the INotifyPropertyChanged interface and in the process saved us having to add 50 additional lines of code. Over the entirety of a larger real world example the savings in writing repetitive boiler plate code will be considerable. | ||
|
||
<br> | ||
|
||
If you'd like to know more about Metalama in general then visit our [website](https://www.postsharp.net/metalama). | ||
|
||
Why not join us on [Slack](https://www.postsharp.net/slack) where you can keep up with what's new and get answers to any technical questions that you might have. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,79 @@ | ||||||
# Common Tasks: Validating Code (Naming Conventions) | ||||||
|
# Common Tasks: Validating Code (Naming Conventions) | |
# Common Tasks: Validating Naming Conventions |
Outdated
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.
We would also need an article about validating references.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Common Tasks: | ||
|
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.
It would be clearer to throw an exception since this is what the aspect is doing.