Skip to content

Commit c7e31ad

Browse files
Merge pull request #35 from ShawnLaMountain/main
Added getter and setter to the Attributes in Source Generator
2 parents a27588d + 203b79f commit c7e31ad

26 files changed

+631
-242
lines changed

.github/workflows/CD.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ jobs:
6161
shell: pwsh
6262

6363
- name: Create NuGet Package
64-
# run: nuget pack ThunderDesign.Net-PCL.nuspec -Version 1.1.4 -OutputDirectory ${{ env.PACKAGE_OUTPUT_DIRECTORY }}
64+
# run: nuget pack ThunderDesign.Net-PCL.nuspec -Version 2.0.17 -OutputDirectory ${{ env.PACKAGE_OUTPUT_DIRECTORY }}
6565
run: nuget pack ThunderDesign.Net-PCL.nuspec -Version ${{ github.event.release.tag_name }} -OutputDirectory ${{ env.PACKAGE_OUTPUT_DIRECTORY }}
6666

6767
- name: Archive NuGet Package
6868
uses: actions/upload-artifact@v4
6969
with:
70-
# name: Package_${{ env.FILE_NAME}}.1.1.4
71-
# path: ${{ env.PACKAGE_OUTPUT_DIRECTORY}}\${{ env.FILE_NAME}}.1.1.4.nupkg
70+
# name: Package_${{ env.FILE_NAME}}.2.0.17
71+
# path: ${{ env.PACKAGE_OUTPUT_DIRECTORY}}\${{ env.FILE_NAME}}.2.0.17.nupkg
7272
name: Package_${{ env.FILE_NAME}}.${{ github.event.release.tag_name }}
7373
path: ${{ env.PACKAGE_OUTPUT_DIRECTORY}}\${{ env.FILE_NAME}}.${{ github.event.release.tag_name }}.nupkg
7474

README.md

Lines changed: 128 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ThunderDesign.Net-PCL.Threading
1+
# ThunderDesign.Net-PCL.Threading
22
[![CI](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CI.yml/badge.svg)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CI.yml)
33
[![CD](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CD.yml/badge.svg)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CD.yml)
44
[![Nuget](https://img.shields.io/nuget/v/ThunderDesign.Net-PCL.Threading)](https://www.nuget.org/packages/ThunderDesign.Net-PCL.Threading)
@@ -107,19 +107,18 @@ With the source generator, you only need to annotate your fields:
107107

108108
```csharp
109109
using ThunderDesign.Net.Threading.Attributes;
110+
110111
public partial class Person
111-
{
112-
[BindableProperty]
112+
{
113+
[BindableProperty]
113114
private string _name;
114115

115116
[Property]
116117
private int _age;
117118
}
118119
```
119120

120-
**What gets generated:**
121-
- A public `Name` property with thread-safe getter/setter and `INotifyPropertyChanged` support.
122-
- A public `Age` property with thread-safe getter/setter.
121+
**What gets generated:**
123122

124123
```csharp
125124
using System.ComponentModel;
@@ -130,7 +129,6 @@ using ThunderDesign.Net.Threading.Interfaces;
130129
public partial class Person : IBindableObject, INotifyPropertyChanged
131130
{
132131
public event PropertyChangedEventHandler PropertyChanged;
133-
134132
protected readonly object _Locker = new object();
135133

136134
public string Name
@@ -150,18 +148,132 @@ public partial class Person : IBindableObject, INotifyPropertyChanged
150148
You can now use your `Person` class like this:
151149

152150
```csharp
153-
var person = new Person();
154-
person.Name = "Alice";
155-
person.Age = 30; // PropertyChanged event will be raised for Name changes if you subscribe to it.
151+
var person = new Person();
152+
person.Name = "Alice";
153+
person.Age = 30;
154+
// PropertyChanged event will be raised for Name changes if you subscribe to it.
156155
```
157156

158-
159157
**No need to manually implement** property notification, thread safety, or boilerplate code—the generator does it for you!
160158

161-
> For more advanced scenarios, you can use attribute parameters to control property behavior (e.g., read-only, also notify other properties, etc.).
159+
> For more advanced scenarios, you can use attribute parameters to control property behavior (e.g., read-only, also notify other properties, or control accessor/property visibility).
162160
161+
---
163162

164-
----
163+
### Advanced: Customizing Getter and Setter Accessors
164+
165+
You can control the visibility of the generated property's getter and setter using the `AccessorAccessibility` enum.
166+
The property itself will use the most accessible (widest) of the getter or setter's accessibilities.
167+
168+
#### Example
169+
170+
```csharp
171+
using ThunderDesign.Net.Threading.Attributes;
172+
using ThunderDesign.Net.Threading.Enums;
173+
174+
public partial class Person
175+
{
176+
// Public getter, private setter (property will be public)
177+
[BindableProperty(getter: AccessorAccessibility.Public, setter: AccessorAccessibility.Private)]
178+
private string _name;
179+
180+
// Internal getter, protected setter (property will be internal)
181+
[Property(getter: AccessorAccessibility.Internal, setter: AccessorAccessibility.Protected)]
182+
private int _age;
183+
}
184+
```
185+
186+
**What gets generated:**
187+
```csharp
188+
public partial class Person
189+
{
190+
public string Name
191+
{
192+
get { return this.GetProperty(ref _name, _Locker); }
193+
private set { this.SetProperty(ref _name, value, _Locker, true); }
194+
}
195+
196+
internal int Age
197+
{
198+
internal get { return this.GetProperty(ref _age, _Locker); }
199+
protected set { this.SetProperty(ref _age, value, _Locker); }
200+
}
201+
}
202+
203+
```
204+
205+
> The property will be as accessible as its most accessible accessor (getter or setter).
206+
> The default for `getter`, and `setter` is `public` if not specified.
207+
208+
**Available options for `AccessorAccessibility`:**
209+
- `Public`
210+
- `Private`
211+
- `Protected`
212+
- `Internal`
213+
- `ProtectedInternal`
214+
- `PrivateProtected`
215+
216+
---
217+
218+
### Advanced: Notify Other Properties
219+
220+
You can notify other properties when a specific property changes by using the `alsoNotify` parameter in the `[BindableProperty]` attribute.
221+
222+
#### Example
223+
```csharp
224+
using ThunderDesign.Net.Threading.Attributes;
225+
226+
public partial class Person
227+
{
228+
[BindableProperty(alsoNotify: new[] { nameof(DisplayName) })]
229+
private string _firstName;
230+
231+
[BindableProperty(alsoNotify: new[] { nameof(DisplayName) })]
232+
private string _lastName;
233+
234+
public string DisplayName => $"{FirstName} {LastName}";
235+
}
236+
```
237+
238+
**What gets generated:**
239+
240+
```csharp
241+
public partial class Person : IBindableObject, INotifyPropertyChanged
242+
{
243+
public event PropertyChangedEventHandler PropertyChanged;
244+
protected readonly object _Locker = new object();
245+
246+
public string FirstName
247+
{
248+
get { return this.GetProperty(ref _firstName, _Locker); }
249+
set
250+
{
251+
if (this.SetProperty(ref _firstName, value, _Locker, true))
252+
{
253+
this.OnPropertyChanged(nameof(DisplayName));
254+
}
255+
}
256+
}
257+
258+
public string LastName
259+
{
260+
get { return this.GetProperty(ref _lastName, _Locker); }
261+
set
262+
{
263+
if (this.SetProperty(ref _lastName, value, _Locker, true))
264+
{
265+
this.OnPropertyChanged(nameof(DisplayName));
266+
}
267+
}
268+
}
269+
270+
public string DisplayName => $"{FirstName} {LastName}";
271+
}
272+
```
273+
274+
> This feature is particularly useful for computed properties like `DisplayName` that depend on other properties.
275+
276+
---
165277

166278
## Installation
167279

@@ -199,4 +311,6 @@ This can be overwritten durring creation or by setting Property `WaitOnNotifyCol
199311
Observable Objects Property `WaitOnNotifyPropertyChanged` has been renamed to Property `WaitOnNotifying`.
200312

201313
Observable Collections Property `WaitOnNotifyCollectionChanged` has been removed and now uses Property `WaitOnNotifying`.
202-
----
314+
----
315+
316+

src/ThunderDesign.Net-PCL.SourceGenerators/PropertyGeneratorHelpers.cs renamed to src/ThunderDesign.Net-PCL.SourceGenerators/Helpers/PropertyGeneratorHelpers.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using Microsoft.CodeAnalysis.CSharp.Syntax;
44
using System.Linq;
55

6-
namespace ThunderDesign.Net_PCL.SourceGenerators
6+
namespace ThunderDesign.Net.SourceGenerators.Helpers
77
{
88
internal static class PropertyGeneratorHelpers
99
{
@@ -74,7 +74,7 @@ public static PropertyFieldInfo GetFieldWithAttribute(GeneratorSyntaxContext con
7474
}
7575
}
7676
}
77-
return default(PropertyFieldInfo);
77+
return default;
7878
}
7979

8080
// Rule 2: Field must start with "_" followed by a letter, or a lowercase letter
@@ -123,17 +123,17 @@ public static bool EventExists(INamedTypeSymbol classSymbol, string eventName, I
123123
public static bool MethodExists(
124124
INamedTypeSymbol classSymbol,
125125
string methodName,
126-
ITypeSymbol[]? parameterTypes = null,
127-
ITypeSymbol? returnType = null)
126+
ITypeSymbol[] parameterTypes = null,
127+
ITypeSymbol returnType = null)
128128
{
129129
return classSymbol.GetMembers()
130130
.OfType<IMethodSymbol>()
131131
.Any(m =>
132132
m.Name == methodName &&
133133
(parameterTypes == null ||
134-
(m.Parameters.Length == parameterTypes.Length &&
134+
m.Parameters.Length == parameterTypes.Length &&
135135
m.Parameters.Select(p => p.Type.ToDisplayString())
136-
.SequenceEqual(parameterTypes.Select(t => t.ToDisplayString())))) &&
136+
.SequenceEqual(parameterTypes.Select(t => t.ToDisplayString()))) &&
137137
(returnType == null || SymbolEqualityComparer.Default.Equals(m.ReturnType, returnType))
138138
);
139139
}

src/ThunderDesign.Net-PCL.SourceGenerators/ThunderDesign.Net-PCL.SourceGenerators.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<LangVersion>latest</LangVersion>
66
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
7-
<RootNamespace>ThunderDesign.Net_PCL.SourceGenerators</RootNamespace>
7+
<RootNamespace>ThunderDesign.Net.SourceGenerators</RootNamespace>
88
<IncludeBuildOutput>false</IncludeBuildOutput>
99
<IncludeAnalyzer>true</IncludeAnalyzer>
1010
<!-- NuGet package metadata -->

0 commit comments

Comments
 (0)