Skip to content

Commit

Permalink
fix #743 removed yield from AutoFac (#745)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisPulman authored Aug 10, 2021
1 parent b1b504d commit e2afa49
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 11 deletions.
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

0 comments on commit e2afa49

Please sign in to comment.