Skip to content

Commit d8e4bdb

Browse files
Merge pull request #30 from ShawnLaMountain/SoureGenerator
Soure generator
2 parents b85d0fa + 2e03516 commit d8e4bdb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2514
-59
lines changed

.github/workflows/CD.yml

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
name: CD
22

33
on:
4+
# workflow_dispatch:
45
release:
56
types: [published]
67

78
env:
89
TITLE: "Thread-Safe Objects"
910
DESCRIPTION: "A combination of generic Thread-Safe objects for .Net development."
10-
TAGS: "thunderdesign visual%2Dstudio c%2Dsharp dotnet%2Dstandard dotnet%2Dframework dotnet%2Dcore cross%2Dplatform pcl%2Dlibrary mono xamarin%2Dforms xamarin%2Dandroid xamarin%2Dios xamarin%2Dmac xamarin%2Duwp unity csharp net dotnet threading bindable binding"
11+
TAGS: "thunderdesign threading thread%2Dsafe thread%2Dsafety threadsafe maui maui%2Dapp c%2Dsharp dotnet%2Dstandard dotnet%2Dframework dotnet%2Dcore cross%2Dplatform pcl%2Dlibrary xamarin unity csharp net dotnet bindable binding"
1112
#FILE_NAME: ex: "ThunderDesign.Net-PCL.Threading"
1213
FILE_NAME: "${{ github.event.repository.name }}"
1314
#REPOSITORY_NAME: ex: "ThunderDesign.Net-PCL.Threading"
@@ -23,18 +24,17 @@ env:
2324

2425
jobs:
2526
pack:
26-
27-
runs-on: [windows-2019]
27+
runs-on: [windows-latest]
2828

2929
steps:
3030
- name: Checkout
3131
uses: actions/checkout@v2
32-
33-
- name: Setup .NET 2.0
32+
33+
- name: Setup .NET 8
3434
uses: actions/setup-dotnet@v1
3535
with:
36-
dotnet-version: 2.0.x
37-
36+
dotnet-version: 8.0.x
37+
3838
- name: Setup MSBuild
3939
uses: microsoft/setup-msbuild@v1.1
4040

@@ -43,13 +43,32 @@ jobs:
4343

4444
- name: Restore NuGet packages.sln
4545
run: nuget restore ./src/${{ env.FILE_NAME}}.sln
46-
46+
47+
- name: Build Solution
48+
run: msbuild ./src/${{ env.FILE_NAME}}.sln /p:Configuration=Release
49+
50+
- name: Prepare .nuspec
51+
run: |
52+
$nuspecPath = "src/${{ env.FILE_NAME }}.nuspec.in"
53+
$nuspec = Get-Content $nuspecPath
54+
$nuspec = $nuspec -replace '\$\{\{ env.FILE_NAME \}\}', '${{ env.FILE_NAME }}'
55+
$nuspec = $nuspec -replace '\$\{\{ env.TITLE \}\}', '${{ env.TITLE }}'
56+
$nuspec = $nuspec -replace '\$\{\{ env.DESCRIPTION \}\}', '${{ env.DESCRIPTION }}'
57+
$nuspec = $nuspec -replace '\$\{\{ env.TAGS \}\}', '${{ env.TAGS }}'
58+
$nuspec = $nuspec -replace '\$\{\{ env.GITHUB_URL \}\}', '${{ env.GITHUB_URL }}'
59+
$nuspec = $nuspec -replace '\$\{\{ env.REPOSITORY_URL \}\}', '${{ env.REPOSITORY_URL }}'
60+
Set-Content ThunderDesign.Net-PCL.nuspec $nuspec
61+
shell: pwsh
62+
4763
- name: Create NuGet Package
48-
run: msbuild ./src/${{ env.FILE_NAME}}.sln -t:pack /p:VersionPrefix=${{ github.event.release.tag_name }} /p:Configuration=Release /p:Title="${{ env.TITLE }}" /p:Description="${{ env.DESCRIPTION }}" /p:PackageTags="${{ env.TAGS }}" /p:Authors=ThunderDesign /p:PackageProjectUrl=${{ env.GITHUB_URL }} /p:PackageLicenseExpression=MIT /p:RepositoryType=git /p:RepositoryUrl=${{ env.REPOSITORY_URL }} /p:PackageReleaseNotes="See ${{ env.REPOSITORY_URL }}/releases/tag/${{ github.event.release.tag_name }}" /p:PackageOutputPath=${{ env.PACKAGE_OUTPUT_DIRECTORY}}
64+
# run: nuget pack ThunderDesign.Net-PCL.nuspec -Version 1.1.4 -OutputDirectory ${{ env.PACKAGE_OUTPUT_DIRECTORY }}
65+
run: nuget pack ThunderDesign.Net-PCL.nuspec -Version ${{ github.event.release.tag_name }} -OutputDirectory ${{ env.PACKAGE_OUTPUT_DIRECTORY }}
4966

5067
- name: Archive NuGet Package
51-
uses: actions/upload-artifact@v2.3.1
68+
uses: actions/upload-artifact@v4
5269
with:
70+
# name: Package_${{ env.FILE_NAME}}.1.1.4
71+
# path: ${{ env.PACKAGE_OUTPUT_DIRECTORY}}\${{ env.FILE_NAME}}.1.1.4.nupkg
5372
name: Package_${{ env.FILE_NAME}}.${{ github.event.release.tag_name }}
5473
path: ${{ env.PACKAGE_OUTPUT_DIRECTORY}}\${{ env.FILE_NAME}}.${{ github.event.release.tag_name }}.nupkg
5574

.github/workflows/CI.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ env:
1414
jobs:
1515
build:
1616

17-
runs-on: [windows-2019]
17+
runs-on: [windows-latest]
1818

1919
steps:
2020
- name: Checkout
2121
uses: actions/checkout@v2
2222

23-
- name: Setup .NET 2.0
23+
- name: Setup .NET 8
2424
uses: actions/setup-dotnet@v1
2525
with:
26-
dotnet-version: 2.0.x
27-
26+
dotnet-version: 8.0.x
27+
2828
- name: Setup MSBuild
2929
uses: microsoft/setup-msbuild@v1.1
3030

README.md

Lines changed: 136 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,48 @@
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)
55
[![License](https://img.shields.io/github/license/ThunderDesign/ThunderDesign.Net-PCL.Threading)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/LICENSE)
6-
[![Net](https://img.shields.io/badge/.net%20standard-v1.0%20--%20v2.1-blue)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/README.md)
6+
[![NetStandard](https://img.shields.io/badge/.net%20standard-v1.0%20--%20v2.1-blue)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/README.md)
7+
[![Net](https://img.shields.io/badge/.net%20-v6.0%20--%20v8.0-blue)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/README.md)
8+
9+
---
710

811
A combination of generic Thread-Safe objects for .Net development.
912

13+
---
14+
15+
<div align="center">
16+
17+
<h2>🚀 <b>Now with .NET 8 support and built-in Source Generators!</b> 🚀</h2>
18+
19+
</div>
20+
21+
> - **.NET 8**: Take advantage of the latest .NET features and performance improvements.
22+
> - **Source Generators**: Eliminate boilerplate and let the library generate thread-safe, bindable properties for you automatically!
23+
>
24+
> _Get started faster, write less code, and enjoy modern .NET development!_
25+
1026
----
1127

1228
A simple C# repository containing a few basic useful Thread-Safe Objects.
1329
### Highlights include:
1430

1531
- Collections
16-
- ObservableDictionaryThreadSafe
17-
- ObservableCollectionThreadSafe
1832
- CollectionThreadSafe
1933
- DictionaryThreadSafe
20-
- SortedListThreadSafe
34+
- HashSetThreadSafe
35+
- LinkedListThreadSafe
2136
- ListThreadSafe
37+
- ObservableCollectionThreadSafe
38+
- ObservableDictionaryThreadSafe
2239
- QueueThreadSafe
40+
- SortedDictionaryThreadSafe
41+
- SortedListThreadSafe
42+
- StackThreadSafe
2343
- DataCollections
24-
- ObservableDataDictionary
2544
- ObservableDataCollection
45+
- ObservableDataDictionary
2646
- DataObjects
2747
- BindableDataObject
2848
- DataObject
@@ -33,10 +53,118 @@ A simple C# repository containing a few basic useful Thread-Safe Objects.
3353
- ObjectExtention
3454
- HelperClasses
3555
- ThreadHelper
56+
- Interfaces
57+
- IBindableCollection
58+
- IBindableDataObject
59+
- IBindableDataObject\<Key>
60+
- IBindableObject
61+
- ICollectionThreadSafe
62+
- IDataObject
63+
- IDataObject\<Key>
64+
- IDictionaryThreadSafe
65+
- IHashSetThreadSafe
66+
- ILinkedListThreadSafe
67+
- IListThreadSafe
68+
- IObservableDataCollection
69+
- IObservableDataCollection\<T>
70+
- ISortedDictionaryThreadSafe
71+
- IStackThreadSafe
3672
- Objects
3773
- BindableObject
3874
- ThreadObject
3975

76+
----
77+
78+
## Source Generators
79+
80+
The `ThunderDesign.Net-PCL.SourceGenerators` project provides Roslyn-based source generators that automate the creation of common boilerplate code for thread-safe and bindable objects in this library. By including this package in your project, you can reduce repetitive code and ensure consistency across your data and collection classes.
81+
82+
### What does it do?
83+
84+
- **Automatic Property Generation:**
85+
The source generator scans your code for fields marked with specific attributes (such as `[BindableProperty]` or `[Property]`) and automatically generates the corresponding properties, including thread-safe accessors and `INotifyPropertyChanged` support where appropriate.
86+
- **Interface Implementation:**
87+
If your class does not already implement interfaces like `IBindableObject`, the generator will add the necessary interface implementations and event wiring.
88+
- **Thread Safety:**
89+
Generated properties use locking patterns to ensure thread safety, matching the patterns used throughout the ThunderDesign.Net-PCL.Threading library.
90+
91+
### How to use
92+
93+
1. **Add the NuGet package:**
94+
Reference the `ThunderDesign.Net-PCL.SourceGenerators` package in your project. If you are building from source, add a project reference to `ThunderDesign.Net-PCL.SourceGenerators.csproj`.
95+
96+
2. **Annotate your fields:**
97+
Use `[BindableProperty]` or `[Property]` attributes on your fields to indicate which properties should be generated. The generator will handle the rest.
98+
99+
3. **Build your project:**
100+
When you build, the source generator will automatically add the generated code to your compilation. You do not need to manually include or maintain the generated files.
101+
102+
4. **Enjoy less boilerplate:**
103+
Your classes will have all the necessary properties, events, and thread-safety mechanisms without manual implementation.
104+
105+
> **Note:** Source generators require Visual Studio 2019 16.9+ or .NET SDK 5.0+ for full support.
106+
107+
### Example Usage
108+
109+
Suppose you want to create a thread-safe, bindable object with automatic property and notification support.
110+
With the source generator, you only need to annotate your fields:
111+
112+
```csharp
113+
using ThunderDesign.Net.Threading.Attributes;
114+
public partial class Person
115+
{
116+
[BindableProperty]
117+
private string _name;
118+
119+
[Property]
120+
private int _age;
121+
}
122+
```
123+
124+
**What gets generated:**
125+
- A public `Name` property with thread-safe getter/setter and `INotifyPropertyChanged` support.
126+
- A public `Age` property with thread-safe getter/setter.
127+
128+
```csharp
129+
using System.ComponentModel;
130+
using System.Runtime.CompilerServices;
131+
using ThunderDesign.Net.Threading.Extentions;
132+
using ThunderDesign.Net.Threading.Interfaces;
133+
134+
public partial class Person : IBindableObject, INotifyPropertyChanged
135+
{
136+
public event PropertyChangedEventHandler PropertyChanged;
137+
138+
protected readonly object _Locker = new object();
139+
140+
public string Name
141+
{
142+
get { return this.GetProperty(ref _name, _Locker); }
143+
set { this.SetProperty(ref _name, value, _Locker, true); }
144+
}
145+
146+
public int Age
147+
{
148+
get { return this.GetProperty(ref _age, _Locker); }
149+
set { this.SetProperty(ref _age, value, _Locker); }
150+
}
151+
}
152+
```
153+
154+
You can now use your `Person` class like this:
155+
156+
```csharp
157+
var person = new Person();
158+
person.Name = "Alice";
159+
person.Age = 30; // PropertyChanged event will be raised for Name changes if you subscribe to it.
160+
```
161+
162+
163+
**No need to manually implement** property notification, thread safety, or boilerplate code—the generator does it for you!
164+
165+
> For more advanced scenarios, you can use attribute parameters to control property behavior (e.g., read-only, also notify other properties, etc.).
166+
167+
40168
----
41169

42170
## Installation
@@ -74,4 +202,5 @@ This can be overwritten durring creation or by setting Property `WaitOnNotifyCol
74202

75203
Observable Objects Property `WaitOnNotifyPropertyChanged` has been renamed to Property `WaitOnNotifying`.
76204

77-
Observable Collections Property `WaitOnNotifyCollectionChanged` has been removed and now uses Property `WaitOnNotifying`.
205+
Observable Collections Property `WaitOnNotifyCollectionChanged` has been removed and now uses Property `WaitOnNotifying`.
206+
----

samples/Xamarin/SimpleBinding/SimpleBinding.Android/Resources/Resource.designer.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/Xamarin/SimpleContacts/SimpleContacts.Android/Resources/Resource.designer.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

samples/Xamarin/SimpleContacts/SimpleContacts.sln

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@ EndProject
88
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleContacts.iOS", "SimpleContacts.iOS\SimpleContacts.iOS.csproj", "{C1F8D9DD-88FB-42E3-A3A1-01F2554FFD1B}"
99
EndProject
1010
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleContacts", "SimpleContacts\SimpleContacts.csproj", "{42D29358-CA82-4C55-9B3D-D8AB994C0FDC}"
11+
ProjectSection(ProjectDependencies) = postProject
12+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2} = {C0A3769B-4580-2360-A1DF-C2A16B56DBF2}
13+
EndProjectSection
1114
EndProject
1215
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThunderDesign.Net-PCL.Threading", "..\..\..\src\ThunderDesign.Net-PCL.Threading\ThunderDesign.Net-PCL.Threading.csproj", "{8616AAA2-E21C-4D85-BE38-4124A58ECA97}"
1316
EndProject
17+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThunderDesign.Net-PCL.SourceGenerators", "..\..\..\src\ThunderDesign.Net-PCL.SourceGenerators\ThunderDesign.Net-PCL.SourceGenerators.csproj", "{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}"
18+
EndProject
19+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThunderDesign.Net-PCL.Threading.Shared", "..\..\..\src\ThunderDesign.Net-PCL.Threading.Shared\ThunderDesign.Net-PCL.Threading.Shared.csproj", "{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}"
20+
EndProject
1421
Global
1522
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1623
Debug|Any CPU = Debug|Any CPU
@@ -87,6 +94,30 @@ Global
8794
{8616AAA2-E21C-4D85-BE38-4124A58ECA97}.Release|iPhone.Build.0 = Release|Any CPU
8895
{8616AAA2-E21C-4D85-BE38-4124A58ECA97}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
8996
{8616AAA2-E21C-4D85-BE38-4124A58ECA97}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
97+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
98+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
99+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Debug|iPhone.ActiveCfg = Debug|Any CPU
100+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Debug|iPhone.Build.0 = Debug|Any CPU
101+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
102+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
103+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
104+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Release|Any CPU.Build.0 = Release|Any CPU
105+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Release|iPhone.ActiveCfg = Release|Any CPU
106+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Release|iPhone.Build.0 = Release|Any CPU
107+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
108+
{C0A3769B-4580-2360-A1DF-C2A16B56DBF2}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
109+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
110+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Debug|Any CPU.Build.0 = Debug|Any CPU
111+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Debug|iPhone.ActiveCfg = Debug|Any CPU
112+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Debug|iPhone.Build.0 = Debug|Any CPU
113+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
114+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
115+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Release|Any CPU.ActiveCfg = Release|Any CPU
116+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Release|Any CPU.Build.0 = Release|Any CPU
117+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Release|iPhone.ActiveCfg = Release|Any CPU
118+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Release|iPhone.Build.0 = Release|Any CPU
119+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
120+
{B7155B3D-8A6E-CA50-5902-5AB2EBEDA57D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
90121
EndGlobalSection
91122
GlobalSection(SolutionProperties) = preSolution
92123
HideSolutionNode = FALSE
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using ThunderDesign.Net_PCL.Threading.Attributes;
5+
6+
namespace SimpleContacts.Models
7+
{
8+
internal partial class TestModel
9+
{
10+
private void TestFirstName()
11+
{
12+
//this.FirstName
13+
}
14+
15+
[BindableProperty]
16+
string _firstName = "John";
17+
}
18+
}

0 commit comments

Comments
 (0)