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

feature: Added Splat.Autofac #234

Merged
merged 1 commit into from
Jan 20, 2019
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
2 changes: 2 additions & 0 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,13 @@ var packagesArtifactDirectory = artifactDirectory + "packages/";
var packageWhitelist = new[]
{
"Splat",
"Splat.Autofac",
};

var packageTestWhitelist = new[]
{
"Splat.Tests",
"Splat.Autofac.Tests",
};

var testFrameworks = new[] { "netcoreapp2.1", "net472" };
Expand Down
88 changes: 88 additions & 0 deletions src/Splat.Autofac.Tests/DependencyResolverTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) 2019 .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 Autofac;
using ReactiveUI;
using Shouldly;
using Xunit;

namespace Splat.Autofac.Tests
{
/// <summary>
/// Tests to show the <see cref="AutofacDependencyResolver"/> works correctly.
/// </summary>
public class DependencyResolverTests
{
/// <summary>
/// Shoulds the resolve views.
/// </summary>
[Fact]
public void AutofacDependencyResolver_Should_Resolve_Views()
{
var builder = new ContainerBuilder();
builder.RegisterType<ViewOne>().As<IViewFor<ViewModelOne>>();
builder.RegisterType<ViewTwo>().As<IViewFor<ViewModelTwo>>();
builder.Build().UseAutofacDependencyResolver();

var viewOne = Locator.Current.GetService(typeof(IViewFor<ViewModelOne>));
var viewTwo = Locator.Current.GetService(typeof(IViewFor<ViewModelTwo>));

viewOne.ShouldNotBeNull();
viewOne.ShouldBeOfType<ViewOne>();
viewTwo.ShouldNotBeNull();
viewTwo.ShouldBeOfType<ViewTwo>();
}

/// <summary>
/// Shoulds the resolve views.
/// </summary>
[Fact]
public void AutofacDependencyResolver_Should_Resolve_Named_View()
{
var builder = new ContainerBuilder();
builder.RegisterType<ViewTwo>().Named<IViewFor<ViewModelTwo>>("Other");
builder.Build().UseAutofacDependencyResolver();

var viewTwo = Locator.Current.GetService(typeof(IViewFor<ViewModelTwo>), "Other");

viewTwo.ShouldNotBeNull();
viewTwo.ShouldBeOfType<ViewTwo>();
}

/// <summary>
/// Shoulds the resolve view models.
/// </summary>
[Fact]
public void AutofacDependencyResolver_Should_Resolve_View_Models()
{
var builder = new ContainerBuilder();
builder.RegisterType<ViewModelOne>().AsSelf();
builder.RegisterType<ViewModelTwo>().AsSelf();
builder.Build().UseAutofacDependencyResolver();

var vmOne = Locator.Current.GetService<ViewModelOne>();
var vmTwo = Locator.Current.GetService<ViewModelTwo>();

vmOne.ShouldNotBeNull();
vmTwo.ShouldNotBeNull();
}

/// <summary>
/// Shoulds the resolve screen.
/// </summary>
[Fact]
public void AutofacDependencyResolver_Should_Resolve_Screen()
{
var builder = new ContainerBuilder();
builder.RegisterType<MockScreen>().As<IScreen>().SingleInstance();
builder.Build().UseAutofacDependencyResolver();

var screen = Locator.Current.GetService<IScreen>();

screen.ShouldNotBeNull();
screen.ShouldBeOfType<MockScreen>();
}
}
}
21 changes: 21 additions & 0 deletions src/Splat.Autofac.Tests/Mocks/MockScreen.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) 2019 .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 ReactiveUI;

namespace Splat.Autofac.Tests
{
/// <summary>
/// An <see cref="IScreen"/> implementation.
/// </summary>
/// <seealso cref="IScreen" />
public class MockScreen : IScreen
{
/// <summary>
/// Gets the Router associated with this Screen.
/// </summary>
public RoutingState Router { get; }
}
}
23 changes: 23 additions & 0 deletions src/Splat.Autofac.Tests/Mocks/ViewModelOne.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2019 .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 ReactiveUI;

namespace Splat.Autofac.Tests
{
/// <summary>
/// View Model One.
/// </summary>
/// <seealso cref="ReactiveObject" />
/// <seealso cref="IRoutableViewModel" />
public class ViewModelOne : ReactiveObject, IRoutableViewModel
{
/// <inheritdoc />
public string UrlPathSegment { get; }

/// <inheritdoc />
public IScreen HostScreen { get; }
}
}
23 changes: 23 additions & 0 deletions src/Splat.Autofac.Tests/Mocks/ViewModelTwo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2019 .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 ReactiveUI;

namespace Splat.Autofac.Tests
{
/// <summary>
/// View Model Two.
/// </summary>
/// <seealso cref="ReactiveObject" />
/// <seealso cref="IRoutableViewModel" />
public class ViewModelTwo : ReactiveObject, IRoutableViewModel
{
/// <inheritdoc />
public string UrlPathSegment { get; }

/// <inheritdoc />
public IScreen HostScreen { get; }
}
}
26 changes: 26 additions & 0 deletions src/Splat.Autofac.Tests/Mocks/ViewOne.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2019 .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 ReactiveUI;

namespace Splat.Autofac.Tests
{
/// <summary>
/// View One.
/// </summary>
/// <seealso cref="ViewModelOne" />
public class ViewOne : IViewFor<ViewModelOne>
{
/// <inheritdoc />
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (ViewModelOne)value;
}

/// <inheritdoc />
public ViewModelOne ViewModel { get; set; }
}
}
27 changes: 27 additions & 0 deletions src/Splat.Autofac.Tests/Mocks/ViewTwo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) 2019 .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 ReactiveUI;

namespace Splat.Autofac.Tests
{
/// <summary>
/// View Two.
/// </summary>
/// <seealso cref="ViewModelTwo" />
[ViewContract("Other")]
public class ViewTwo : IViewFor<ViewModelTwo>
{
/// <inheritdoc />
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (ViewModelTwo)value;
}

/// <inheritdoc />
public ViewModelTwo ViewModel { get; set; }
}
}
25 changes: 25 additions & 0 deletions src/Splat.Autofac.Tests/Splat.Autofac.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netcoreapp2.1;net472</TargetFrameworks>

<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);1591;CA1707;SA1633</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Autofac" Version="4.8.1" />
<PackageReference Include="ReactiveUI" Version="9.8.15" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Splat.Autofac\Splat.Autofac.csproj" />
<ProjectReference Include="..\Splat\Splat.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="xunit.runner.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions src/Splat.Autofac.Tests/xunit.runner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"shadowCopy": false
}
139 changes: 139 additions & 0 deletions src/Splat.Autofac/AutofacDependencyResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright (c) 2019 .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.Collections;
using System.Collections.Generic;
using System.Linq;
using Autofac;
using Autofac.Core;

namespace Splat.Autofac
{
/// <summary>
/// Autofac implementation for <see cref="IMutableDependencyResolver"/>.
/// </summary>
public class AutofacDependencyResolver : IMutableDependencyResolver
{
private IContainer _container;

/// <summary>
/// Initializes a new instance of the <see cref="AutofacDependencyResolver"/> class.
/// </summary>
/// <param name="container">The container.</param>
public AutofacDependencyResolver(IContainer container)
{
_container = container;
}

/// <inheritdoc />
public virtual object GetService(Type serviceType, string contract = null)
{
try
{
return string.IsNullOrEmpty(contract)
? _container.Resolve(serviceType)
: _container.ResolveNamed(contract, serviceType);
}
catch (DependencyResolutionException)
{
return null;
}
}

/// <inheritdoc />
public virtual IEnumerable<object> GetServices(Type serviceType, string contract = null)
{
try
{
var enumerableType = typeof(IEnumerable<>).MakeGenericType(serviceType);
object instance = string.IsNullOrEmpty(contract)
? _container.Resolve(enumerableType)
: _container.ResolveNamed(contract, enumerableType);
return ((IEnumerable)instance).Cast<object>();
}
catch (DependencyResolutionException)
{
return null;
}
}

/// <summary>
/// Register a function with the resolver which will generate a object
/// for the specified service type.
/// Optionally a contract can be registered which will indicate
/// that that registration will only work with that contract.
/// Most implementations will use a stack based approach to allow for multile items to be registered.
/// </summary>
/// <param name="factory">The factory function which generates our object.</param>
/// <param name="serviceType">The type which is used for the registration.</param>
/// <param name="contract">A optional contract value which will indicates to only generate the value if this contract is specified.</param>
public virtual void Register(Func<object> factory, Type serviceType, string contract = null)
{
var builder = new ContainerBuilder();
if (string.IsNullOrEmpty(contract))
{
builder.Register(x => factory()).As(serviceType).AsImplementedInterfaces();
}
else
{
builder.Register(x => factory()).Named(contract, serviceType).AsImplementedInterfaces();
}
}

/// <summary>
/// Unregisters the current item based on the specified type and contract.
/// https://stackoverflow.com/questions/5091101/is-it-possible-to-remove-an-existing-registration-from-autofac-container-builder.
/// </summary>
/// <param name="serviceType">The service type to unregister.</param>
/// <param name="contract">The optional contract value, which will only remove the value associated with the contract.</param>
/// <exception cref="System.NotImplementedException">This is not implemented by default.</exception>
/// <inheritdoc />
public virtual void UnregisterCurrent(Type serviceType, string contract = null)
{
throw new NotImplementedException();
}

/// <summary>
/// Unregisters all the values associated with the specified type and contract.
/// https://stackoverflow.com/questions/5091101/is-it-possible-to-remove-an-existing-registration-from-autofac-container-builder.
/// </summary>
/// <param name="serviceType">The service type to unregister.</param>
/// <param name="contract">The optional contract value, which will only remove the value associated with the contract.</param>
/// <exception cref="System.NotImplementedException">This is not implemented by default.</exception>
/// <inheritdoc />
public virtual void UnregisterAll(Type serviceType, string contract = null)
{
throw new NotImplementedException();
}

/// <inheritdoc />
public virtual IDisposable ServiceRegistrationCallback(Type serviceType, string contract, Action<IDisposable> callback)
{
// this method is not used by RxUI
throw new NotImplementedException();
}

/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Disposes of the instance.
/// </summary>
/// <param name="disposing">Whether or not the instance is disposing.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_container?.Dispose();
_container = null;
}
}
}
}
Loading