Skip to content

Commit 44b3366

Browse files
authored
Feature add IViewFor for Maui (#17)
1 parent fd76d5f commit 44b3366

13 files changed

+532
-169
lines changed

src/Directory.Packages.props

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
<PackageVersion Include="Roslynator.Analyzers" Version="4.12.4" />
2222

2323
<PackageVersion Include="ReactiveUI" Version="20.1.1" />
24+
<PackageVersion Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
25+
<PackageVersion Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
26+
2427
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
2528
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" />
2629
<PackageVersion Include="PolySharp" Version="1.14.1" />
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using ReactiveUI.SourceGenerators;
7+
8+
namespace SGReactiveUI.SourceGenerators.Test.Maui
9+
{
10+
/// <summary>
11+
/// IViewForTest.
12+
/// </summary>
13+
/// <seealso cref="NavigationPage" />
14+
[IViewFor(nameof(TestViewModel))]
15+
public partial class IViewForTest : Shell;
16+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
5+
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
6+
<UseMaui>true</UseMaui>
7+
<ImplicitUsings>enable</ImplicitUsings>
8+
<Nullable>enable</Nullable>
9+
<IsPackable>false</IsPackable>
10+
<LangVersion>latest</LangVersion>
11+
12+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
13+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
14+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
15+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
16+
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
17+
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
18+
</PropertyGroup>
19+
20+
<ItemGroup>
21+
<PackageReference Include="ReactiveUI" />
22+
<PackageReference Include="Microsoft.Maui.Controls" />
23+
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" />
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<ProjectReference Include="..\ReactiveUI.SourceGenerators\ReactiveUI.SourceGenerators.csproj" OutputItemType="Analyzer" />
28+
</ItemGroup>
29+
30+
</Project>
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using System.Reactive;
7+
using System.Reactive.Linq;
8+
using System.Runtime.Serialization;
9+
using System.Text.Json.Serialization;
10+
using ReactiveUI;
11+
using ReactiveUI.SourceGenerators;
12+
13+
namespace SGReactiveUI.SourceGenerators.Test;
14+
15+
/// <summary>
16+
/// TestClass.
17+
/// </summary>
18+
[DataContract]
19+
public partial class TestViewModel : ReactiveObject
20+
{
21+
[JsonInclude]
22+
[DataMember]
23+
[ObservableAsProperty]
24+
private double _test2Property;
25+
26+
[JsonInclude]
27+
[Reactive]
28+
[DataMember]
29+
private int _test1Property;
30+
31+
/// <summary>
32+
/// Initializes a new instance of the <see cref="TestViewModel"/> class.
33+
/// </summary>
34+
public TestViewModel()
35+
{
36+
InitializeCommands();
37+
38+
Console.Out.WriteLine(Test1Command);
39+
Console.Out.WriteLine(Test2Command);
40+
Console.Out.WriteLine(Test3AsyncCommand);
41+
Console.Out.WriteLine(Test4AsyncCommand);
42+
Console.Out.WriteLine(Test5StringToIntCommand);
43+
Console.Out.WriteLine(Test6ArgOnlyCommand);
44+
Console.Out.WriteLine(Test7ObservableCommand);
45+
Console.Out.WriteLine(Test8ObservableCommand);
46+
Console.Out.WriteLine(Test9AsyncCommand);
47+
Console.Out.WriteLine(Test10AsyncCommand);
48+
Test1Command?.Execute().Subscribe();
49+
Test2Command?.Execute().Subscribe(r => Console.Out.WriteLine(r));
50+
Test3AsyncCommand?.Execute().Subscribe();
51+
Test4AsyncCommand?.Execute().Subscribe(r => Console.Out.WriteLine(r));
52+
Test5StringToIntCommand?.Execute("100").Subscribe(Console.Out.WriteLine);
53+
Test6ArgOnlyCommand?.Execute("Hello World").Subscribe();
54+
Test7ObservableCommand?.Execute().Subscribe();
55+
56+
_test2PropertyHelper = Test8ObservableCommand!.ToProperty(this, x => x.Test2Property);
57+
58+
Test8ObservableCommand?.Execute(100).Subscribe(Console.Out.WriteLine);
59+
Console.Out.WriteLine($"Test2Property Value: {Test2}");
60+
Console.Out.WriteLine($"Test2Property underlying Value: {_test2Property}");
61+
62+
Test9AsyncCommand?.ThrownExceptions.Subscribe(Console.Out.WriteLine);
63+
var cancel = Test9AsyncCommand?.Execute().Subscribe();
64+
Task.Delay(1000).Wait();
65+
cancel?.Dispose();
66+
67+
Test10AsyncCommand?.Execute(200).Subscribe(r => Console.Out.WriteLine(r));
68+
}
69+
70+
/// <summary>
71+
/// Gets the instance.
72+
/// </summary>
73+
/// <value>
74+
/// The instance.
75+
/// </value>
76+
public static TestViewModel Instance { get; } = new();
77+
78+
/// <summary>
79+
/// Gets the can execute test1.
80+
/// </summary>
81+
/// <value>
82+
/// The can execute test1.
83+
/// </value>
84+
#pragma warning disable CA1822 // Mark members as static
85+
public IObservable<bool> CanExecuteTest1 => Observable.Return(true);
86+
#pragma warning restore CA1822 // Mark members as static
87+
88+
/// <summary>
89+
/// Test1s this instance.
90+
/// </summary>
91+
[ReactiveCommand(CanExecute = nameof(CanExecuteTest1))]
92+
[property: JsonInclude]
93+
private void Test1() => Console.Out.WriteLine("Test1");
94+
95+
/// <summary>
96+
/// Test2s this instance.
97+
/// </summary>
98+
/// <returns>Rectangle.</returns>
99+
[ReactiveCommand]
100+
private Point Test2() => default;
101+
102+
/// <summary>
103+
/// Test3s the asynchronous.
104+
/// </summary>
105+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
106+
[ReactiveCommand]
107+
private async Task Test3Async() => await Task.Delay(0);
108+
109+
/// <summary>
110+
/// Test4s the asynchronous.
111+
/// </summary>
112+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
113+
[ReactiveCommand]
114+
private async Task<Point> Test4Async() => await Task.FromResult(new Point(100, 100));
115+
116+
/// <summary>
117+
/// Test5s the string to int.
118+
/// </summary>
119+
/// <param name="str">The string.</param>
120+
/// <returns>int.</returns>
121+
[ReactiveCommand]
122+
private int Test5StringToInt(string str) => int.Parse(str);
123+
124+
/// <summary>
125+
/// Test6s the argument only.
126+
/// </summary>
127+
/// <param name="str">The string.</param>
128+
[ReactiveCommand]
129+
private void Test6ArgOnly(string str) => Console.Out.WriteLine($">>> {str}");
130+
131+
/// <summary>
132+
/// Test7s the observable.
133+
/// </summary>
134+
/// <returns>An Observable of Unit.</returns>
135+
[ReactiveCommand]
136+
private IObservable<Unit> Test7Observable() => Observable.Return(Unit.Default);
137+
138+
/// <summary>
139+
/// Test8s the observable.
140+
/// </summary>
141+
/// <param name="i">The i.</param>
142+
/// <returns>An Observable of int.</returns>
143+
[ReactiveCommand]
144+
private IObservable<double> Test8Observable(int i) => Observable.Return(i + 10.0);
145+
146+
[ReactiveCommand]
147+
private async Task Test9Async(CancellationToken ct) => await Task.Delay(2000, ct);
148+
149+
[ReactiveCommand]
150+
private async Task<Point> Test10Async(int size, CancellationToken ct) => await Task.FromResult(new Point(size, size));
151+
}

src/ReactiveUI.SourceGenerators.Execute/Program.cs

Lines changed: 1 addition & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -3,169 +3,15 @@
33
// The .NET Foundation licenses this file to you under the MIT license.
44
// See the LICENSE file in the project root for full license information.
55

6-
using System.Drawing;
7-
using System.Reactive;
8-
using System.Reactive.Linq;
9-
using System.Runtime.Serialization;
10-
using System.Text.Json.Serialization;
11-
using ReactiveUI;
12-
using ReactiveUI.SourceGenerators;
13-
146
namespace SGReactiveUI.SourceGenerators.Test;
157

16-
#pragma warning disable SA1402 // File may only contain a single type
17-
#pragma warning disable SA1649 // File name should match first type name
18-
#pragma warning disable CA1822 // Mark members as static
19-
208
/// <summary>
219
/// EntryPoint.
2210
/// </summary>
23-
public static class EntryPoint
11+
public static class Program
2412
{
2513
/// <summary>
2614
/// Defines the entry point of the application.
2715
/// </summary>
2816
public static void Main() => _ = TestViewModel.Instance;
2917
}
30-
31-
/// <summary>
32-
/// TestClass.
33-
/// </summary>
34-
[DataContract]
35-
public partial class TestViewModel : ReactiveObject
36-
{
37-
[JsonInclude]
38-
[DataMember]
39-
[ObservableAsProperty]
40-
private double _test2Property;
41-
42-
[JsonInclude]
43-
[Reactive]
44-
[DataMember]
45-
private int _test1Property;
46-
47-
/// <summary>
48-
/// Initializes a new instance of the <see cref="TestViewModel"/> class.
49-
/// </summary>
50-
public TestViewModel()
51-
{
52-
InitializeCommands();
53-
54-
Console.Out.WriteLine(Test1Command);
55-
Console.Out.WriteLine(Test2Command);
56-
Console.Out.WriteLine(Test3AsyncCommand);
57-
Console.Out.WriteLine(Test4AsyncCommand);
58-
Console.Out.WriteLine(Test5StringToIntCommand);
59-
Console.Out.WriteLine(Test6ArgOnlyCommand);
60-
Console.Out.WriteLine(Test7ObservableCommand);
61-
Console.Out.WriteLine(Test8ObservableCommand);
62-
Console.Out.WriteLine(Test9AsyncCommand);
63-
Console.Out.WriteLine(Test10AsyncCommand);
64-
Test1Command?.Execute().Subscribe();
65-
Test2Command?.Execute().Subscribe(r => Console.Out.WriteLine(r));
66-
Test3AsyncCommand?.Execute().Subscribe();
67-
Test4AsyncCommand?.Execute().Subscribe(r => Console.Out.WriteLine(r));
68-
Test5StringToIntCommand?.Execute("100").Subscribe(Console.Out.WriteLine);
69-
Test6ArgOnlyCommand?.Execute("Hello World").Subscribe();
70-
Test7ObservableCommand?.Execute().Subscribe();
71-
72-
_test2PropertyHelper = Test8ObservableCommand!.ToProperty(this, x => x.Test2Property);
73-
74-
Test8ObservableCommand?.Execute(100).Subscribe(Console.Out.WriteLine);
75-
Console.Out.WriteLine($"Test2Property Value: {Test2}");
76-
Console.Out.WriteLine($"Test2Property underlying Value: {_test2Property}");
77-
78-
Test9AsyncCommand?.ThrownExceptions.Subscribe(Console.Out.WriteLine);
79-
var cancel = Test9AsyncCommand?.Execute().Subscribe();
80-
Task.Delay(1000).Wait();
81-
cancel?.Dispose();
82-
83-
Test10AsyncCommand?.Execute(200).Subscribe(r => Console.Out.WriteLine(r));
84-
85-
Console.ReadLine();
86-
}
87-
88-
/// <summary>
89-
/// Gets the instance.
90-
/// </summary>
91-
/// <value>
92-
/// The instance.
93-
/// </value>
94-
public static TestViewModel Instance { get; } = new();
95-
96-
/// <summary>
97-
/// Gets the can execute test1.
98-
/// </summary>
99-
/// <value>
100-
/// The can execute test1.
101-
/// </value>
102-
public IObservable<bool> CanExecuteTest1 => Observable.Return(true);
103-
104-
/// <summary>
105-
/// Test1s this instance.
106-
/// </summary>
107-
[ReactiveCommand(CanExecute = nameof(CanExecuteTest1))]
108-
[property: JsonInclude]
109-
private void Test1() => Console.Out.WriteLine("Test1");
110-
111-
/// <summary>
112-
/// Test2s this instance.
113-
/// </summary>
114-
/// <returns>Rectangle.</returns>
115-
[ReactiveCommand]
116-
private Rectangle Test2() => default;
117-
118-
/// <summary>
119-
/// Test3s the asynchronous.
120-
/// </summary>
121-
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
122-
[ReactiveCommand]
123-
private async Task Test3Async() => await Task.Delay(0);
124-
125-
/// <summary>
126-
/// Test4s the asynchronous.
127-
/// </summary>
128-
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
129-
[ReactiveCommand]
130-
private async Task<Rectangle> Test4Async() => await Task.FromResult(new Rectangle(0, 0, 100, 100));
131-
132-
/// <summary>
133-
/// Test5s the string to int.
134-
/// </summary>
135-
/// <param name="str">The string.</param>
136-
/// <returns>int.</returns>
137-
[ReactiveCommand]
138-
private int Test5StringToInt(string str) => int.Parse(str);
139-
140-
/// <summary>
141-
/// Test6s the argument only.
142-
/// </summary>
143-
/// <param name="str">The string.</param>
144-
[ReactiveCommand]
145-
private void Test6ArgOnly(string str) => Console.Out.WriteLine($">>> {str}");
146-
147-
/// <summary>
148-
/// Test7s the observable.
149-
/// </summary>
150-
/// <returns>An Observable of Unit.</returns>
151-
[ReactiveCommand]
152-
private IObservable<Unit> Test7Observable() => Observable.Return(Unit.Default);
153-
154-
/// <summary>
155-
/// Test8s the observable.
156-
/// </summary>
157-
/// <param name="i">The i.</param>
158-
/// <returns>An Observable of int.</returns>
159-
[ReactiveCommand]
160-
private IObservable<double> Test8Observable(int i) => Observable.Return(i + 10.0);
161-
162-
[ReactiveCommand]
163-
private async Task Test9Async(CancellationToken ct) => await Task.Delay(2000, ct);
164-
165-
[ReactiveCommand]
166-
private async Task<Rectangle> Test10Async(int size, CancellationToken ct) => await Task.FromResult(new Rectangle(0, 0, size, size));
167-
}
168-
169-
#pragma warning restore CA1822 // Mark members as static
170-
#pragma warning restore SA1649 // File name should match first type name
171-
#pragma warning restore SA1402 // File may only contain a single type

0 commit comments

Comments
 (0)