|
| 1 | +Hi, |
| 2 | + |
| 3 | +This is the final email in our series introducing you to Metalama. |
| 4 | + |
| 5 | +Today, let's look into more advanced patterns in C# and explore how you can automate them using Metalama. |
| 6 | + |
| 7 | +## INotifyPropertyChanged |
| 8 | + |
| 9 | +If you're building a desktop or mobile app, or even a web app with client-side Blazor, you're likely familiar with the `INotifyPropertyChanged` interface. While it seems simple to implement, it can become cumbersome and error-prone as you add more complex properties and dependencies between objects. |
| 10 | + |
| 11 | +Enter the `[Observable]` aspect from the open-source [Metalama.Patterns.Observability](https://doc.postsharp.net/metalama/patterns/observability?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly) package. |
| 12 | + |
| 13 | +```csharp |
| 14 | +[Observable] |
| 15 | +public class Person |
| 16 | +``` |
| 17 | + |
| 18 | +This aspect handles `INotifyPropertyChanged` implementation for you, supporting a rich set of scenarios: |
| 19 | + |
| 20 | +- **Automatic properties:** |
| 21 | + |
| 22 | + ```csharp |
| 23 | + public string? FirstName { get; set; } |
| 24 | + ``` |
| 25 | + |
| 26 | +- **Properties depending on other properties or fields:** |
| 27 | + |
| 28 | + ```csharp |
| 29 | + public string FullName => $"{this.FirstName} {this._lastName}"; |
| 30 | + ``` |
| 31 | + |
| 32 | +- **Properties depending on child objects, such as `Person`:** |
| 33 | + |
| 34 | + ```csharp |
| 35 | + public string FullName => $"{this.Person.FirstName} {this.Person.LastName}"; |
| 36 | + ``` |
| 37 | + |
| 38 | +- **Properties depending on properties of the base type.** |
| 39 | + |
| 40 | +Consider how much boilerplate code you'd need to properly implement `INotifyPropertyChanged` for these scenarios and how much you would save with Metalama! To see the work Metalama does for you, [check out the diff](https://doc.postsharp.net/metalama/patterns/observability/standard-cases?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly). |
| 41 | + |
| 42 | +It's not just about saving code, but also about enhancing code quality. Remember the last bug when you forgot to add a call to `OnPropertyChanged` for a computed property? With `[Observable]`, since dependency discovery is fully automatic, this won't happen any more. |
| 43 | + |
| 44 | +Read more details about `[Observable]` in our [documentation](https://doc.postsharp.net/metalama/patterns/observability?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly). |
| 45 | +
|
| 46 | +## Builder Pattern |
| 47 | + |
| 48 | +Another frequent source of boilerplate code is the [Builder pattern](https://blog.postsharp.net/builder-pattern-with-metalama?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly), which has become ubiquitous in modern C# due to the increased use of immutable types. |
| 49 | +
|
| 50 | +Consider a simple immutable class: |
| 51 | + |
| 52 | +```csharp |
| 53 | +public partial class Song |
| 54 | +{ |
| 55 | + public string Title { get; } |
| 56 | + |
| 57 | + public ImmutableArray<string> Artists { get; } |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +The code supporting the Builder class would look like this: |
| 62 | + |
| 63 | +```csharp |
| 64 | +public partial class Song |
| 65 | +{ |
| 66 | + private Song(string title, ImmutableArray<string> artists) |
| 67 | + { |
| 68 | + this.Title = title; |
| 69 | + this.Artists = artists; |
| 70 | + } |
| 71 | + |
| 72 | + public Builder ToBuilder() => new Builder(this); |
| 73 | + |
| 74 | + public class Builder |
| 75 | + { |
| 76 | + public string Title { get; set; } |
| 77 | + |
| 78 | + public ImmutableArray<string>.Builder Artists { get; } |
| 79 | + |
| 80 | + public Builder() |
| 81 | + { |
| 82 | + this.Artists = ImmutableArray.CreateBuilder<string>(); |
| 83 | + } |
| 84 | + |
| 85 | + public Builder(Song song) |
| 86 | + { |
| 87 | + this.Title = song.Title; |
| 88 | + this.Artists = song.Artists.ToBuilder(); |
| 89 | + } |
| 90 | + |
| 91 | + public Song Build() => new Song(this.Title, this.Artists.ToImmutable()); |
| 92 | + } |
| 93 | +} |
| 94 | +``` |
| 95 | + |
| 96 | +How repetitive! Do you really want to write this code by hand? Thankfully, [this can be automated using Metalama](https://doc.postsharp.net/metalama/examples/builder?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly), and you can tailor the code generation pattern to fit your needs. |
| 97 | +
|
| 98 | +## Other Examples |
| 99 | + |
| 100 | +We can't cover all use cases of Metalama in a single email, so before wrapping up this sequence, here's a list of Metalama use cases: |
| 101 | + |
| 102 | +- [Parameter validation](https://doc.postsharp.net/metalama/examples/validation?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly) and [code contracts](https://doc.postsharp.net/metalama/patterns/contracts); |
| 103 | +- [Logging](https://doc.postsharp.net/metalama/examples/log?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly); |
| 104 | +- [Exception handling](https://doc.postsharp.net/metalama/examples/exception-handling?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly) with or without [Polly](https://doc.postsharp.net/metalama/examples/exception-handling/retry/retry-5); |
| 105 | +- [Caching](https://doc.postsharp.net/metalama/patterns/caching?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly) and [memoization](https://doc.postsharp.net/metalama/patterns/memoization?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly); |
| 106 | +- [INotifyPropertyChanged](https://doc.postsharp.net/metalama/patterns/observability), WPF [commands](https://doc.postsharp.net/metalama/patterns/wpf/command?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly), and [dependency properties](https://doc.postsharp.net/metalama/patterns/wpf/dependency-property?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly); |
| 107 | +- [Architecture verification](https://doc.postsharp.net/metalama/conceptual/architecture?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly); |
| 108 | +- [Change tracking](https://doc.postsharp.net/metalama/examples/change-tracking?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly) and the [Memento pattern](https://doc.postsharp.net/metalama/examples/memento?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly). |
| 109 | +- [Cloning](https://doc.postsharp.net/metalama/examples/clone?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly); |
| 110 | +- [Builder](https://doc.postsharp.net/metalama/examples/builde?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly), and [Singleton](https://doc.postsharp.net/metalama/examples/singleton?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly) patterns; |
| 111 | +- [ToString](https://doc.postsharp.net/metalama/examples/tostring) generation. |
| 112 | +
|
| 113 | +For more use cases and open-source aspect implementations, visit the [Metalama Marketplace](https://www.postsharp.net/metalama/marketplace?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly). |
| 114 | +
|
| 115 | +## How to Get Started? |
| 116 | + |
| 117 | +Start using Metalama today. Add the `Metalama.Framework` package to your project and activate _Metalama Free_, our free edition that lets you use up to three aspect types (e.g., logging, caching, and `INotifyPropertyChanged`) regardless of your project's size. |
| 118 | + |
| 119 | +For a better development experience, download the optional [Visual Studio Tools for Metalama](https://www.postsharp.net/metalama/download?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly). |
| 120 | +
|
| 121 | +If you have any questions, feel free to reach out to our community on [GitHub](https://github.com/orgs/postsharp/discussions) or on our [Slack workspace](https://www.postsharp.net/slack?mtm_campaign=awareness&mtm_kwd=email5&mtm_source=instantly). |
| 122 | +
|
| 123 | +Happy meta-programming with Metalama! |
0 commit comments