Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #743 removed yield from AutoFac #745

Merged
merged 2 commits into from
Aug 10, 2021
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
35 changes: 33 additions & 2 deletions src/ReactiveUI.DI.Tests/AutoFacReactiveUIDependencyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@

using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using Autofac;
using FluentAssertions;
using ReactiveUI.DI.Tests.Mocks;
using Splat;
using Splat.Autofac;
using Xunit;
Expand All @@ -22,7 +24,7 @@ public class AutoFacReactiveUIDependencyTests
/// Should register ReactiveUI binding type converters.
/// </summary>
[Fact]
public void AutofacDependencyResolver_Should_Register_ReactiveUI_BindingTypeConverters()
public void AutofacDependencyResolverShouldRegisterReactiveUIBindingTypeConverters()
{
// Invoke RxApp which initializes the ReactiveUI platform.
var builder = new ContainerBuilder();
Expand All @@ -42,7 +44,7 @@ public void AutofacDependencyResolver_Should_Register_ReactiveUI_BindingTypeConv
/// Should register ReactiveUI creates command bindings.
/// </summary>
[Fact]
public void AutofacDependencyResolver_Should_Register_ReactiveUI_CreatesCommandBinding()
public void AutofacDependencyResolverShouldRegisterReactiveUICreatesCommandBinding()
{
// Invoke RxApp which initializes the ReactiveUI platform.
var builder = new ContainerBuilder();
Expand All @@ -57,5 +59,34 @@ public void AutofacDependencyResolver_Should_Register_ReactiveUI_CreatesCommandB
converters.Should().Contain(x => x.GetType() == typeof(CreatesCommandBindingViaEvent));
converters.Should().Contain(x => x.GetType() == typeof(CreatesCommandBindingViaCommandParameter));
}

/// <summary>
/// Automatics the fac when any test.
/// </summary>
[Fact]
public void AutoFacWhenAnyTest()
{
var builder = new ContainerBuilder();

var autofacResolver = builder.UseAutofacDependencyResolver();
Locator.CurrentMutable.RegisterConstant(new ActivatingViewFetcher(), typeof(IActivationForViewFetcher));
autofacResolver.InitializeSplat();
autofacResolver.InitializeReactiveUI();
var container = builder.Build();

var vm = new ActivatingViewModel();
var fixture = new ActivatingView { ViewModel = vm };

Assert.Equal(0, vm.IsActiveCount);
Assert.Equal(0, fixture.IsActiveCount);

fixture.Loaded.OnNext(Unit.Default);
Assert.Equal(1, vm.IsActiveCount);
Assert.Equal(1, fixture.IsActiveCount);

fixture.Unloaded.OnNext(Unit.Default);
Assert.Equal(0, vm.IsActiveCount);
Assert.Equal(0, fixture.IsActiveCount);
}
}
}
82 changes: 82 additions & 0 deletions src/ReactiveUI.DI.Tests/Mocks/ActivatingView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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.

using System;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Subjects;

namespace ReactiveUI.DI.Tests.Mocks
{
/// <summary>
/// Activating View.
/// </summary>
/// <seealso cref="ReactiveUI.ReactiveObject" />
/// <seealso cref="ReactiveUI.IActivatableView" />
public sealed class ActivatingView : ReactiveObject, IViewFor<ActivatingViewModel>, IDisposable
{
private int _count;
private ActivatingViewModel _viewModel;

/// <summary>
/// Initializes a new instance of the <see cref="ActivatingView"/> class.
/// </summary>
public ActivatingView()
{
this.WhenActivated(d =>
{
_count++;
d(Disposable.Create(() => _count--));
});
}

/// <summary>
/// Gets the count.
/// </summary>
/// <value>
/// The count.
/// </value>
public int IsActiveCount => _count;

/// <summary>
/// Gets the loaded.
/// </summary>
public Subject<Unit> Loaded { get; } = new();

/// <summary>
/// Gets the unloaded.
/// </summary>
public Subject<Unit> Unloaded { get; } = new();

/// <summary>
/// Gets or sets the view model.
/// </summary>
public ActivatingViewModel ViewModel
{
get => _viewModel;
set => this.RaiseAndSetIfChanged(ref _viewModel, value);
}

/// <summary>
/// Gets or sets the view model.
/// </summary>
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (ActivatingViewModel)value;
}

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Loaded.Dispose();
Unloaded.Dispose();
GC.SuppressFinalize(this);
}
}
}
49 changes: 49 additions & 0 deletions src/ReactiveUI.DI.Tests/Mocks/ActivatingViewFetcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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.

using System;
using System.Reactive.Linq;

namespace ReactiveUI.DI.Tests.Mocks
{
/// <summary>
/// Simulates a activating view fetcher.
/// </summary>
public class ActivatingViewFetcher : IActivationForViewFetcher
{
/// <summary>
/// Determines the priority that the Activation View Fetcher
/// will be able to process the view type.
/// 0 means it cannot activate the View, value larger than 0
/// indicates it can activate the View.
/// The class derived off IActivationForViewFetcher which returns
/// the highest affinity value will be used to activate the View.
/// </summary>
/// <param name="view">The type for the View.</param>
/// <returns>
/// The affinity value which is equal to 0 or above.
/// </returns>
public int GetAffinityForView(Type view) => view == typeof(ActivatingView) ? 100 : 0;

/// <summary>
/// Gets a Observable which will activate the View.
/// This is called after the GetAffinityForView method.
/// </summary>
/// <param name="view">The view to get the activation observable for.</param>
/// <returns>
/// A Observable which will returns if Activation was successful.
/// </returns>
/// <exception cref="ArgumentNullException">The view is null.</exception>
public IObservable<bool> GetActivationForView(IActivatableView view)
{
if (view is not ActivatingView av)
{
throw new ArgumentNullException(nameof(view));
}

return av.Loaded.Select(_ => true).Merge(av.Unloaded.Select(_ => false));
}
}
}
40 changes: 40 additions & 0 deletions src/ReactiveUI.DI.Tests/Mocks/ActivatingViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.

using System.Reactive.Disposables;

namespace ReactiveUI.DI.Tests.Mocks
{
/// <summary>
/// ActivatingViewModel.
/// </summary>
/// <seealso cref="ReactiveUI.ReactiveObject" />
public class ActivatingViewModel : ReactiveObject, IActivatableViewModel
{
/// <summary>
/// Initializes a new instance of the <see cref="ActivatingViewModel"/> class.
/// </summary>
public ActivatingViewModel()
{
Activator = new ViewModelActivator();

this.WhenActivated(d =>
{
IsActiveCount++;
d(Disposable.Create(() => IsActiveCount--));
});
}

/// <summary>
/// Gets or sets the Activator which will be used by the View when Activation/Deactivation occurs.
/// </summary>
public ViewModelActivator Activator { get; protected set; }

/// <summary>
/// Gets or sets the active count.
/// </summary>
public int IsActiveCount { get; protected set; }
}
}
2 changes: 2 additions & 0 deletions src/ReactiveUI.DI.Tests/ReactiveUI.DI.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

<PropertyGroup>
<TargetFrameworks>net462;net472;netcoreapp3;net5.0;</TargetFrameworks>
<NoWarn>$(NoWarn);1591;CA1707;SA1633;CA2000</NoWarn>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<Choose>
Expand Down
12 changes: 3 additions & 9 deletions src/Splat.Autofac/AutofacDependencyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,25 +107,19 @@ public virtual IEnumerable<object> GetServices(Type? serviceType, string? contra

if (isNull && instance is IEnumerable<NullServiceType> nullService)
{
foreach (var item in nullService)
{
yield return item.Factory()!;
}

yield break;
return nullService.Select(item => item.Factory()!);
}
else if (!isNull && instance is not null)
{
yield return new object[] { instance };
yield break;
return ((IEnumerable)instance).Cast<object>();
}
}
finally
{
// no op
}

yield return Array.Empty<object>();
return Array.Empty<object>();
}
}

Expand Down