Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/ReactiveUI.Fody.Helpers/ObservableAsPropertyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ public static class ObservableAsPropertyExtensions
/// </exception>
public static ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(
this IObservable<TRet> item,
TObj? source,
Expression<Func<TObj, TRet?>> property,
TObj source,
Expression<Func<TObj, TRet>> property,
bool deferSubscription = false,
IScheduler? scheduler = null)
where TObj : ReactiveObject
Expand Down Expand Up @@ -88,8 +88,8 @@ public static ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(
/// </exception>
public static ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(
this IObservable<TRet> item,
TObj? source,
Expression<Func<TObj, TRet?>> property,
TObj source,
Expression<Func<TObj, TRet>> property,
TRet initialValue,
bool deferSubscription = false,
IScheduler? scheduler = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ namespace ReactiveUI.Fody.Helpers
}
public static class ObservableAsPropertyExtensions
{
public static ReactiveUI.ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(this System.IObservable<TRet> item, TObj? source, System.Linq.Expressions.Expression<System.Func<TObj, TRet?>> property, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null)
public static ReactiveUI.ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(this System.IObservable<TRet> item, TObj source, System.Linq.Expressions.Expression<System.Func<TObj, TRet>> property, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null)
where TObj : ReactiveUI.ReactiveObject { }
public static ReactiveUI.ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(this System.IObservable<TRet> item, TObj? source, System.Linq.Expressions.Expression<System.Func<TObj, TRet?>> property, TRet initialValue, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null)
public static ReactiveUI.ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(this System.IObservable<TRet> item, TObj source, System.Linq.Expressions.Expression<System.Func<TObj, TRet>> property, TRet initialValue, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null)
where TObj : ReactiveUI.ReactiveObject { }
}
[System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.All)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ namespace ReactiveUI.Fody.Helpers
}
public static class ObservableAsPropertyExtensions
{
public static ReactiveUI.ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(this System.IObservable<TRet> item, TObj? source, System.Linq.Expressions.Expression<System.Func<TObj, TRet?>> property, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null)
public static ReactiveUI.ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(this System.IObservable<TRet> item, TObj source, System.Linq.Expressions.Expression<System.Func<TObj, TRet>> property, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null)
where TObj : ReactiveUI.ReactiveObject { }
public static ReactiveUI.ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(this System.IObservable<TRet> item, TObj? source, System.Linq.Expressions.Expression<System.Func<TObj, TRet?>> property, TRet initialValue, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null)
public static ReactiveUI.ObservableAsPropertyHelper<TRet> ToPropertyEx<TObj, TRet>(this System.IObservable<TRet> item, TObj source, System.Linq.Expressions.Expression<System.Func<TObj, TRet>> property, TRet initialValue, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null)
where TObj : ReactiveUI.ReactiveObject { }
}
[System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.All)]
Expand Down
4 changes: 2 additions & 2 deletions src/ReactiveUI.Splat.Tests/ReactiveUI.Splat.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
Expand All @@ -10,7 +10,7 @@

<ItemGroup>
<PackageReference Include="Splat.Autofac" Version="12.*" />
<PackageReference Include="Splat.DryIoc" Version="11.*" />
<PackageReference Include="Splat.DryIoc" Version="12.*" />
<PackageReference Include="Splat.Ninject" Version="12.*" />
</ItemGroup>

Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/ReactiveUI.Tests/Mocks/MockBindListView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public MockBindListView()
.Where(i => i != null)
.Cast<MockBindListItemViewModel>()
.Do(_ => ItemList.UnselectAll())
.InvokeCommand(this, v => v.ViewModel!.SelectItem).DisposeWith(d);
.InvokeCommand(this, v => v!.ViewModel!.SelectItem).DisposeWith(d);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,13 +456,13 @@ public void ToProperty_NameOf_ValidValuesProduced(string[] testWords, string[] f

fixture.ObservableForProperty(x => x.LastThreeLettersOfOneWord, beforeChange: true).ToObservableChangeSet(ImmediateScheduler.Instance).Bind(out var lastThreeChanging).Subscribe();

var changing = new[] { firstThreeChanging, lastThreeChanging };
var changing = new[] { firstThreeChanging!, lastThreeChanging };

fixture.ObservableForProperty(x => x.FirstThreeLettersOfOneWord, beforeChange: false).ToObservableChangeSet(ImmediateScheduler.Instance).Bind(out var firstThreeChanged).Subscribe();

fixture.ObservableForProperty(x => x.LastThreeLettersOfOneWord, beforeChange: false).ToObservableChangeSet(ImmediateScheduler.Instance).Bind(out var lastThreeChanged).Subscribe();

var changed = new[] { firstThreeChanged, lastThreeChanged };
var changed = new[] { firstThreeChanged!, lastThreeChanged };

Assert.True(changed.All(x => x.Count == 0));
Assert.True(changing.All(x => x.Count == 0));
Expand Down Expand Up @@ -551,11 +551,11 @@ public void NullableTypesTestShouldntNeedDecorators2_ToProperty()
fixture.WhenAnyValue(
x => x.ProjectService.ProjectsNullable,
x => x.AccountService.AccountUsersNullable)
.Where(tuple => tuple.Item1.Any() && tuple.Item2.Any())
.Where(tuple => tuple.Item1?.Count > 0 && tuple.Item2?.Count > 0)
.Select(tuple =>
{
var (projects, users) = tuple;
return (int?)users.Values.Count(x => !string.IsNullOrWhiteSpace(x?.LastName));
return users?.Values.Count(x => !string.IsNullOrWhiteSpace(x?.LastName));
})
.ToProperty(fixture, x => x.AccountsFound, out fixture._accountsFound);

Expand Down
6 changes: 3 additions & 3 deletions src/ReactiveUI.Tests/Resolvers/DependencyResolverTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,13 @@ private static Dictionary<Type, List<Type>> GetServicesThatShouldBeRegistered(IR

new Registrations().Register((factory, serviceType) =>
{
if (serviceTypeToImplementationTypes.TryGetValue(serviceType, out var implementationTypes) == false)
if (serviceTypeToImplementationTypes.TryGetValue(serviceType!, out var implementationTypes) == false)
{
implementationTypes = new List<Type>();
serviceTypeToImplementationTypes.Add(serviceType, implementationTypes);
serviceTypeToImplementationTypes.Add(serviceType!, implementationTypes);
}

implementationTypes.Add(factory().GetType());
implementationTypes.Add(factory()!.GetType());
});

new PlatformRegistrations().Register((factory, serviceType) =>
Expand Down
35 changes: 33 additions & 2 deletions src/ReactiveUI.Tests/WhenAny/Mockups/HostTestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,50 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.Reactive.Linq;

namespace ReactiveUI.Tests
{
/// <summary>
/// A host test fixture.
/// </summary>
public class HostTestFixture : ReactiveObject
{
private readonly ObservableAsPropertyHelper<string?> _ownerName;
private TestFixture? _Child;

private OwnerClass? _owner;
private NonObservableTestFixture? _PocoChild;

private int _SomeOtherParam;

public HostTestFixture()
{
_ownerName = this.WhenAnyValue(x => x.Owner)
.WhereNotNull()
.Select(owner => owner.WhenAnyValue(x => x.Name))
.Switch()
.ToProperty(this, x => x.OwnerName);
}

/// <summary>
/// Gets the name of the owner.
/// </summary>
/// <value>
/// The name of the owner.
/// </value>
public string? OwnerName => _ownerName.Value;

/// <summary>
/// Gets or sets the owner.
/// </summary>
/// <value>
/// The owner.
/// </value>
public OwnerClass? Owner
{
get => _owner;
set => this.RaiseAndSetIfChanged(ref _owner, value);
}

/// <summary>
/// Gets or sets the child.
/// </summary>
Expand Down
28 changes: 28 additions & 0 deletions src/ReactiveUI.Tests/WhenAny/Mockups/OwnerClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

namespace ReactiveUI.Tests
{
/// <summary>
/// Owner Class.
/// </summary>
/// <seealso cref="ReactiveUI.ReactiveObject" />
public class OwnerClass : ReactiveObject
{
private string? _name;

/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>
/// The name.
/// </value>
public string? Name
{
get => _name;
set => this.RaiseAndSetIfChanged(ref _name, value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -636,9 +636,9 @@ public void WhenAnyValueShouldWorkEvenWithNormalProperties()
};

var output1 = new List<string?>();
var output2 = new List<int>();
var output2 = new List<int?>();
fixture.WhenAnyValue(x => x.PocoProperty).Subscribe(output1.Add);
fixture.WhenAnyValue(x => x.IsOnlyOneWord, x => x.Length).Subscribe(output2.Add);
fixture.WhenAnyValue(x => x.IsOnlyOneWord, x => x?.Length).Subscribe(output2.Add);

Assert.Equal(1, output1.Count);
Assert.Equal("Bamf", output1[0]);
Expand Down Expand Up @@ -784,11 +784,11 @@ public void NullableTypesTestShouldntNeedDecorators2()
fixture.WhenAnyValue(
x => x.ProjectService.ProjectsNullable,
x => x.AccountService.AccountUsersNullable)
.Where(tuple => tuple.Item1.Any() && tuple.Item2.Any())
.Where(tuple => tuple.Item1?.Count > 0 && tuple.Item2?.Count > 0)
.Select(tuple =>
{
var (projects, users) = tuple;
return users.Values.Where(x => !string.IsNullOrWhiteSpace(x?.LastName));
return users?.Values.Where(x => !string.IsNullOrWhiteSpace(x?.LastName));
})
.Subscribe(dict => result = dict);

Expand All @@ -804,7 +804,7 @@ public void NonNullableTypesTestShouldntNeedDecorators()
WhenAnyTestFixture fixture = new();
IEnumerable<AccountUser>? result = null;
fixture.WhenAnyValue(x => x.AccountService.AccountUsers)
.Where(users => users.Any())
.Where(users => users.Count > 0)
.Select(users => users.Values.Where(x => !string.IsNullOrWhiteSpace(x.LastName)))
.Subscribe(dict => result = dict);

Expand All @@ -818,15 +818,15 @@ public void NonNullableTypesTestShouldntNeedDecorators()
public void NonNullableTypesTestShouldntNeedDecorators2()
{
WhenAnyTestFixture fixture = new();
IEnumerable<AccountUser?>? result = null;
IEnumerable<AccountUser>? result = null;
fixture.WhenAnyValue(
x => x.ProjectService.Projects,
x => x.AccountService.AccountUsers)
.Where(tuple => tuple.Item1.Any() && tuple.Item2.Any())
.Where(tuple => tuple.Item1?.Count > 0 && tuple.Item2?.Count > 0)
.Select(tuple =>
{
var (projects, users) = tuple;
return users.Values.Where(x => !string.IsNullOrWhiteSpace(x?.LastName));
return users!.Values.Where(x => !string.IsNullOrWhiteSpace(x.LastName));
})
.Subscribe(dict => result = dict);

Expand All @@ -842,16 +842,52 @@ public void WhenAnyValueWith1Paramerters()
WhenAnyTestFixture fixture = new();
string? result = null;
fixture.WhenAnyValue(
x => x.Value1)
.Select(value =>
{
return value;
})
.Subscribe(value => result = value);
x => x.Value1).Subscribe(value => result = value);

Assert.Equal(result, "1");
}

[Fact]
public void WhenAnyValueWith1ParamertersSequentialCheck()
{
WhenAnyTestFixture fixture = new();
var result = string.Empty;
fixture.Value1 = null!;
fixture.WhenAnyValue(
x => x.Value1).Subscribe(value => result = value);

Assert.Equal(result, null);

fixture.Value1 = "A";
Assert.Equal(result, "A");

fixture.Value1 = "B";
Assert.Equal(result, "B");

fixture.Value1 = null!;
Assert.Equal(result, null);
}

[Fact]
public void WhenAnyValueWith1ParamertersSequentialCheckNullable()
{
WhenAnyTestFixture fixture = new();
var result = string.Empty;
fixture.WhenAnyValue(
x => x.Value2).Subscribe(value => result = value);

Assert.Equal(result, null);

fixture.Value2 = "A";
Assert.Equal(result, "A");

fixture.Value2 = "B";
Assert.Equal(result, "B");

fixture.Value2 = null;
Assert.Equal(result, null);
}

/// <summary>
/// Whens any value with2 paramerters returns tuple.
/// </summary>
Expand Down Expand Up @@ -1289,5 +1325,31 @@ public void WhenAnyValueWith12ParamertersReturnsValues()

Assert.Equal(result, "1357911");
}

[Fact]
public void WhenAnyValueWithToProperty()
{
HostTestFixture? fixture = new();

Assert.Equal(null, fixture.Owner);
Assert.Equal(null, fixture.OwnerName);

fixture.Owner = new();
fixture.Owner.Name = "Fred";
Assert.NotNull(fixture.Owner);
Assert.Equal("Fred", fixture.OwnerName);

fixture.Owner.Name = "Wilma";
Assert.Equal("Wilma", fixture.OwnerName);

fixture.Owner.Name = null;
Assert.Equal(null, fixture.OwnerName);

fixture.Owner.Name = "Barney";
Assert.Equal("Barney", fixture.OwnerName);

fixture.Owner.Name = "Betty";
Assert.Equal("Betty", fixture.OwnerName);
}
}
}
18 changes: 4 additions & 14 deletions src/ReactiveUI/Mixins/ReactiveNotifyPropertyChangedMixin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,10 @@ public static class ReactiveNotifyPropertyChangedMixin
/// notifications for the given property.</returns>
public static IObservable<IObservedChange<TSender, TValue>> ObservableForProperty<TSender, TValue>(
this TSender? item,
Expression<Func<TSender, TValue?>> property,
Expression<Func<TSender, TValue>> property,
bool beforeChange = false,
bool skipInitial = true)
{
if (item is null)
{
throw new ArgumentNullException(nameof(item));
}

if (property is null)
{
throw new ArgumentNullException(nameof(property));
Expand Down Expand Up @@ -105,7 +100,7 @@ public static IObservable<IObservedChange<TSender, TValue>> ObservableForPropert
/// notifications for the given property.</returns>
public static IObservable<TRet> ObservableForProperty<TSender, TValue, TRet>(
this TSender? item,
Expression<Func<TSender, TValue?>> property,
Expression<Func<TSender, TValue>> property,
Func<TValue?, TRet> selector,
bool beforeChange = false) // TODO: Create Test
where TSender : class
Expand Down Expand Up @@ -139,13 +134,8 @@ public static IObservable<IObservedChange<TSender, TValue>> SubscribeToExpressio
bool skipInitial = true,
bool suppressWarnings = false) // TODO: Create Test
{
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}

IObservable<IObservedChange<object?, object?>> notifier =
Observable.Return(new ObservedChange<object?, object?>(null, null!, source));
Observable.Return(new ObservedChange<object?, object?>(null, null, source));

var chain = Reflection.Rewrite(expression).GetExpressionChain();
notifier = chain.Aggregate(notifier, (n, expr) => n
Expand All @@ -168,7 +158,7 @@ public static IObservable<IObservedChange<TSender, TValue>> SubscribeToExpressio
throw new InvalidCastException($"Unable to cast from {val.GetType()} to {typeof(TValue)}.");
}

return new ObservedChange<TSender, TValue>(source, expression, (TValue)val!);
return new ObservedChange<TSender, TValue>(source!, expression, (TValue)val!);
});

return r.DistinctUntilChanged(x => x.Value);
Expand Down
Loading