diff --git a/src/Splat.Common.Test/IViewModelOne.cs b/src/Splat.Common.Test/IViewModelOne.cs
new file mode 100644
index 000000000..d0de11aa5
--- /dev/null
+++ b/src/Splat.Common.Test/IViewModelOne.cs
@@ -0,0 +1,14 @@
+// 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 Splat.Common.Test
+{
+ ///
+ /// Interface for ViewModelOne.
+ ///
+ public interface IViewModelOne
+ {
+ }
+}
diff --git a/src/Splat.Common.Test/ViewModelOne.cs b/src/Splat.Common.Test/ViewModelOne.cs
index 56babd24d..f2da11f66 100644
--- a/src/Splat.Common.Test/ViewModelOne.cs
+++ b/src/Splat.Common.Test/ViewModelOne.cs
@@ -8,7 +8,13 @@ namespace Splat.Common.Test
///
/// View Model One.
///
- public class ViewModelOne
+ public class ViewModelOne : IViewModelOne
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ViewModelOne()
+ {
+ }
}
}
diff --git a/src/Splat.Microsoft.Extensions.DependencyInjection/MicrosoftDependencyResolver.cs b/src/Splat.Microsoft.Extensions.DependencyInjection/MicrosoftDependencyResolver.cs
index 7a393e659..b7348d478 100644
--- a/src/Splat.Microsoft.Extensions.DependencyInjection/MicrosoftDependencyResolver.cs
+++ b/src/Splat.Microsoft.Extensions.DependencyInjection/MicrosoftDependencyResolver.cs
@@ -115,7 +115,7 @@ public virtual IEnumerable GetServices(Type serviceType, string? contrac
services = dic?
.GetFactories(contract)
.Select(f => f())
- ?? Enumerable.Empty();
+ ?? Array.Empty();
}
return services;
@@ -370,7 +370,7 @@ public bool TryRemoveContract(string contract) =>
public IEnumerable> GetFactories(string contract) =>
_dictionary.TryGetValue(contract, out var collection)
? collection ?? Enumerable.Empty>()
- : Enumerable.Empty>();
+ : Array.Empty>();
public void AddFactory(string contract, Func factory) =>
_dictionary.AddOrUpdate(contract, _ => new List> { factory }, (_, list) =>
diff --git a/src/Splat.SimpleInjector/SimpleInjectorDependencyResolver.cs b/src/Splat.SimpleInjector/SimpleInjectorDependencyResolver.cs
index 1d88f6161..92452ed7a 100644
--- a/src/Splat.SimpleInjector/SimpleInjectorDependencyResolver.cs
+++ b/src/Splat.SimpleInjector/SimpleInjectorDependencyResolver.cs
@@ -66,7 +66,7 @@ public IEnumerable GetServices(Type serviceType, string? contract = null
return new[] { registration.GetInstance() };
}
- return Enumerable.Empty();
+ return Array.Empty();
}
}
diff --git a/src/Splat.Tests/API/ApiApprovalTests.SplatProject.net5.0.approved.txt b/src/Splat.Tests/API/ApiApprovalTests.SplatProject.net5.0.approved.txt
index c11747f59..f53faf455 100644
--- a/src/Splat.Tests/API/ApiApprovalTests.SplatProject.net5.0.approved.txt
+++ b/src/Splat.Tests/API/ApiApprovalTests.SplatProject.net5.0.approved.txt
@@ -163,6 +163,8 @@ namespace Splat
public static System.Collections.Generic.IEnumerable GetServices(this Splat.IReadonlyDependencyResolver resolver, string? contract = null) { }
public static void Register(this Splat.IMutableDependencyResolver resolver, System.Func factory, string? contract = null)
where T : notnull { }
+ public static void Register(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
public static void RegisterConstant(this Splat.IMutableDependencyResolver resolver, object value, System.Type serviceType, string? contract = null) { }
public static void RegisterConstant(this Splat.IMutableDependencyResolver resolver, T value, string? contract = null)
where T : notnull { }
@@ -568,6 +570,23 @@ namespace Splat
public static System.Tuple DivideWithPadding(this System.Drawing.RectangleF value, float sliceAmount, float padding, Splat.RectEdge fromEdge) { }
public static System.Drawing.RectangleF InvertWithin(this System.Drawing.RectangleF value, System.Drawing.RectangleF containingRect) { }
}
+ public static class ResolverMixins
+ {
+ public static Splat.IMutableDependencyResolver RegisterAnd(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
+ public static Splat.IMutableDependencyResolver RegisterAnd(this Splat.IMutableDependencyResolver resolver, System.Func factory, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterAnd(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
+ public static Splat.IMutableDependencyResolver RegisterAnd(this Splat.IMutableDependencyResolver resolver, System.Func factory, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterConstantAnd(this Splat.IMutableDependencyResolver resolver, object value, System.Type serviceType, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterConstantAnd(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
+ public static Splat.IMutableDependencyResolver RegisterConstantAnd(this Splat.IMutableDependencyResolver resolver, T value, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterLazySingletonAnd(this Splat.IMutableDependencyResolver resolver, System.Func valueFactory, System.Type serviceType, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterLazySingletonAnd(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
+ public static Splat.IMutableDependencyResolver RegisterLazySingletonAnd(this Splat.IMutableDependencyResolver resolver, System.Func valueFactory, string? contract = null) { }
+ }
public static class ServiceLocationInitialization
{
public static void InitializeSplat(this Splat.IMutableDependencyResolver resolver) { }
diff --git a/src/Splat.Tests/API/ApiApprovalTests.SplatProject.netcoreapp3.1.approved.txt b/src/Splat.Tests/API/ApiApprovalTests.SplatProject.netcoreapp3.1.approved.txt
index 2b7497bd6..fee459022 100644
--- a/src/Splat.Tests/API/ApiApprovalTests.SplatProject.netcoreapp3.1.approved.txt
+++ b/src/Splat.Tests/API/ApiApprovalTests.SplatProject.netcoreapp3.1.approved.txt
@@ -163,6 +163,8 @@ namespace Splat
public static System.Collections.Generic.IEnumerable GetServices(this Splat.IReadonlyDependencyResolver resolver, string? contract = null) { }
public static void Register(this Splat.IMutableDependencyResolver resolver, System.Func factory, string? contract = null)
where T : notnull { }
+ public static void Register(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
public static void RegisterConstant(this Splat.IMutableDependencyResolver resolver, object value, System.Type serviceType, string? contract = null) { }
public static void RegisterConstant(this Splat.IMutableDependencyResolver resolver, T value, string? contract = null)
where T : notnull { }
@@ -568,6 +570,23 @@ namespace Splat
public static System.Tuple DivideWithPadding(this System.Drawing.RectangleF value, float sliceAmount, float padding, Splat.RectEdge fromEdge) { }
public static System.Drawing.RectangleF InvertWithin(this System.Drawing.RectangleF value, System.Drawing.RectangleF containingRect) { }
}
+ public static class ResolverMixins
+ {
+ public static Splat.IMutableDependencyResolver RegisterAnd(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
+ public static Splat.IMutableDependencyResolver RegisterAnd(this Splat.IMutableDependencyResolver resolver, System.Func factory, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterAnd(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
+ public static Splat.IMutableDependencyResolver RegisterAnd(this Splat.IMutableDependencyResolver resolver, System.Func factory, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterConstantAnd(this Splat.IMutableDependencyResolver resolver, object value, System.Type serviceType, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterConstantAnd(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
+ public static Splat.IMutableDependencyResolver RegisterConstantAnd(this Splat.IMutableDependencyResolver resolver, T value, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterLazySingletonAnd(this Splat.IMutableDependencyResolver resolver, System.Func valueFactory, System.Type serviceType, string? contract = null) { }
+ public static Splat.IMutableDependencyResolver RegisterLazySingletonAnd(this Splat.IMutableDependencyResolver resolver, string? contract = null)
+ where T : new() { }
+ public static Splat.IMutableDependencyResolver RegisterLazySingletonAnd(this Splat.IMutableDependencyResolver resolver, System.Func valueFactory, string? contract = null) { }
+ }
public static class ServiceLocationInitialization
{
public static void InitializeSplat(this Splat.IMutableDependencyResolver resolver) { }
diff --git a/src/Splat.Tests/LocatorSerialRegisterTests.cs b/src/Splat.Tests/LocatorSerialRegisterTests.cs
new file mode 100644
index 000000000..ca5f7f1f7
--- /dev/null
+++ b/src/Splat.Tests/LocatorSerialRegisterTests.cs
@@ -0,0 +1,370 @@
+// 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 FluentAssertions;
+using Splat.Tests.Mocks;
+using Xunit;
+
+namespace Splat.Tests
+{
+ ///
+ /// Tests to confirm that the locator is working.
+ ///
+ public class LocatorSerialRegisterTests
+ {
+ ///
+ /// Tests if the registrations are not empty on no external registrations.
+ ///
+ [Fact]
+ public void InitializeSplat_RegistrationsNotEmptyNoRegistrations()
+ {
+ // this is using the internal constructor
+ var testLocator = new InternalLocator();
+ var logManager = testLocator.Current.GetService(typeof(ILogManager));
+ var logger = testLocator.Current.GetService(typeof(ILogger));
+
+ Assert.NotNull(logManager);
+ Assert.NotNull(logger);
+
+ Assert.IsType(logger);
+ Assert.IsType(logManager);
+ }
+
+ ///
+ /// Tests that if we use a contract it returns null entries for that type.
+ ///
+ [Fact]
+ public void InitializeSplat_ContractRegistrationsNullNoRegistration()
+ {
+ var testLocator = new InternalLocator();
+ var logManager = testLocator.Current.GetService(typeof(ILogManager), "test");
+ var logger = testLocator.Current.GetService(typeof(ILogger), "test");
+
+ Assert.Null(logManager);
+ Assert.Null(logger);
+ }
+
+ ///
+ /// Tests using the extension methods that the retrieving of the default InitializeSplat() still work.
+ ///
+ [Fact]
+ public void InitializeSplat_ExtensionMethodsNotNull()
+ {
+ var testLocator = new InternalLocator();
+ var logManager = testLocator.Current.GetService();
+ var logger = testLocator.Current.GetService();
+
+ Assert.NotNull(logManager);
+ Assert.NotNull(logger);
+
+ Assert.IsType(logger);
+ Assert.IsType(logManager);
+ }
+
+ ///
+ /// Tests to make sure that the locator's fire the resolver changed notifications.
+ ///
+ [Fact]
+ public void WithoutSuppress_NotificationsHappen()
+ {
+ var testLocator = new InternalLocator();
+ var originalLocator = testLocator.Internal;
+
+ int numberNotifications = 0;
+ Action notificationAction = () => numberNotifications++;
+
+ testLocator.RegisterResolverCallbackChanged(notificationAction);
+
+ testLocator.SetLocator(new ModernDependencyResolver());
+ testLocator.SetLocator(new ModernDependencyResolver());
+
+ // 2 for the changes, 1 for the callback being immediately called.
+ Assert.Equal(3, numberNotifications);
+
+ testLocator.SetLocator(originalLocator);
+ }
+
+ ///
+ /// Tests to make sure that the locator's don't fire the resolver changed notifications if they are suppressed.
+ ///
+ [Fact]
+ public void WithSuppression_NotificationsDontHappen()
+ {
+ var testLocator = new InternalLocator();
+ var originalLocator = testLocator.Internal;
+
+ using (testLocator.SuppressResolverCallbackChangedNotifications())
+ {
+ int numberNotifications = 0;
+ Action notificationAction = () => numberNotifications++;
+
+ testLocator.RegisterResolverCallbackChanged(notificationAction);
+
+ testLocator.SetLocator(new ModernDependencyResolver());
+ testLocator.SetLocator(new ModernDependencyResolver());
+
+ Assert.Equal(0, numberNotifications);
+
+ testLocator.SetLocator(originalLocator);
+ }
+ }
+
+ ///
+ /// Tests to make sure that the locator's don't fire the resolver changed notifications if we use WithResolver().
+ ///
+ [Fact]
+ public void WithResolver_NotificationsDontHappen()
+ {
+ int numberNotifications = 0;
+ Action notificationAction = () => numberNotifications++;
+
+ var testLocator = new InternalLocator();
+ testLocator.RegisterResolverCallbackChanged(notificationAction);
+
+ using (testLocator.Internal.WithResolver())
+ {
+ using (testLocator.Internal.WithResolver())
+ {
+ }
+ }
+
+ // 1 due to the fact the callback is called when we register.
+ Assert.Equal(1, numberNotifications);
+ }
+
+ ///
+ /// Tests to make sure that the locator's don't fire the resolver changed notifications if we use WithResolver().
+ ///
+ [Fact]
+ public void WithResolver_NotificationsNotSuppressedHappen()
+ {
+ int numberNotifications = 0;
+ Action notificationAction = () => numberNotifications++;
+
+ Locator.RegisterResolverCallbackChanged(notificationAction);
+
+ using (Locator.GetLocator().WithResolver(false))
+ {
+ using (Locator.GetLocator().WithResolver(false))
+ {
+ }
+ }
+
+ // 1 due to the fact the callback is called when we register.
+ // 2 for, 1 for change to resolver, 1 for change back
+ // 2 for, 1 for change to resolver, 1 for change back
+ Assert.Equal(5, numberNotifications);
+ }
+
+ ///
+ /// Tests to make sure that the unregister all functions correctly.
+ /// This is a test when there are values registered.
+ ///
+ [Fact]
+ public void ModernDependencyResolver_UnregisterAll_WithValuesWorks()
+ {
+ var currentMutable = new ModernDependencyResolver();
+
+ var dummy1 = new DummyObjectClass1();
+ var dummy2 = new DummyObjectClass2();
+ var dummy3 = new DummyObjectClass3();
+
+ var testContracts = new[] { string.Empty, "test" };
+
+ foreach (var testContract in testContracts)
+ {
+ currentMutable.RegisterConstantAnd(dummy1, testContract)
+ .RegisterConstantAnd(dummy2, testContract)
+ .RegisterConstant(dummy3, testContract);
+ }
+
+ foreach (var testContract in testContracts)
+ {
+ var items = currentMutable.GetServices(testContract);
+
+ items.Should().BeEquivalentTo(new IDummyInterface[] { dummy1, dummy2, dummy3 });
+
+ currentMutable.UnregisterAll(testContract);
+
+ items = currentMutable.GetServices(testContract);
+
+ items.Should().BeEmpty();
+ }
+ }
+
+ ///
+ /// Tests to make sure that the unregister all functions correctly.
+ /// This is a test when there are values not registered.
+ ///
+ [Fact]
+ public void ModernDependencyResolver_UnregisterAll_NoValuesWorks()
+ {
+ var currentMutable = new ModernDependencyResolver();
+
+ var items = currentMutable.GetServices();
+
+ items.Should().BeEmpty();
+
+ currentMutable.UnregisterAll();
+
+ items = currentMutable.GetServices();
+
+ items.Should().BeEmpty();
+ }
+
+ ///
+ /// Tests tomake sure that the unregister current functions correctly.
+ /// This is a test when there are values registered.
+ ///
+ [Fact]
+ public void ModernDependencyResolver_ConstantUnregisterCurrent_WithValuesWorks()
+ {
+ var dummy1 = new DummyObjectClass1();
+ var dummy2 = new DummyObjectClass2();
+ var dummy3 = new DummyObjectClass3();
+
+ var currentMutable = new ModernDependencyResolver();
+
+ var testContracts = new[] { string.Empty, "test" };
+
+ foreach (var testContract in testContracts)
+ {
+ currentMutable.RegisterConstantAnd(dummy1, testContract)
+ .RegisterConstantAnd(dummy2, testContract)
+ .RegisterConstant(dummy3, testContract);
+ }
+
+ foreach (var testContract in testContracts)
+ {
+ var items = currentMutable.GetServices(testContract);
+
+ items.Should().BeEquivalentTo(new IDummyInterface[] { dummy1, dummy2, dummy3 });
+
+ currentMutable.UnregisterCurrent(testContract);
+
+ items = currentMutable.GetServices(testContract);
+
+ items.Should().BeEquivalentTo(new IDummyInterface[] { dummy1, dummy2 });
+ }
+ }
+
+ ///
+ /// Tests tomake sure that the unregister current functions correctly.
+ /// This is a test when there are values registered.
+ ///
+ [Fact]
+ public void ModernDependencyResolver_UnregisterCurrent_WithValuesWorks()
+ {
+ var currentMutable = new ModernDependencyResolver();
+
+ var testContracts = new[] { string.Empty, "test" };
+
+ foreach (var testContract in testContracts)
+ {
+ currentMutable.RegisterAnd(testContract)
+ .RegisterAnd(testContract)
+ .Register(testContract);
+ }
+
+ foreach (var testContract in testContracts)
+ {
+ var items = currentMutable.GetServices(testContract);
+
+ items.Should().HaveCount(3);
+
+ currentMutable.UnregisterCurrent(testContract);
+
+ items = currentMutable.GetServices(testContract);
+
+ items.Should().HaveCount(2);
+ }
+ }
+
+ ///
+ /// Tests to make sure that the unregister all functions correctly.
+ /// This is a test when there are values not registered.
+ ///
+ [Fact]
+ public void ModernDependencyResolver_UnregisterCurrent_NoValuesWorks()
+ {
+ var currentMutable = new ModernDependencyResolver();
+ var items = currentMutable.GetServices();
+
+ items.Should().BeEmpty();
+
+ currentMutable.UnregisterCurrent();
+
+ items = currentMutable.GetServices();
+
+ items.Should().BeEmpty();
+ }
+
+ ///
+ /// Tests to make sure that the unregister all functions correctly.
+ /// This is a test when there are values not registered.
+ ///
+ [Fact]
+ public void FuncDependencyResolver_UnregisterAll()
+ {
+ bool unregisterAllCalled = false;
+ Type type = null;
+ string contract = null;
+
+ var currentMutable = new FuncDependencyResolver(
+ (funcType, funcContract) => Array.Empty(),
+ unregisterAll: (passedType, passedContract) =>
+ {
+ unregisterAllCalled = true;
+ contract = passedContract;
+ type = passedType;
+ });
+
+ currentMutable.UnregisterAll();
+ type.Should().Be(typeof(IDummyInterface));
+ contract.Should().BeNull();
+ unregisterAllCalled.Should().BeTrue();
+
+ unregisterAllCalled = false;
+ currentMutable.UnregisterAll("test");
+ type.Should().Be(typeof(IEnableLogger));
+ contract.Should().Be("test");
+ unregisterAllCalled.Should().BeTrue();
+ }
+
+ ///
+ /// Tests tomake sure that the unregister current functions correctly.
+ /// This is a test when there are values registered.
+ ///
+ [Fact]
+ public void FuncDependencyResolver_UnregisterCurrent()
+ {
+ bool unregisterAllCalled = false;
+ Type type = null;
+ string contract = null;
+
+ var currentMutable = new FuncDependencyResolver(
+ (funcType, funcContract) => Array.Empty(),
+ unregisterCurrent: (passedType, passedContract) =>
+ {
+ unregisterAllCalled = true;
+ contract = passedContract;
+ type = passedType;
+ });
+
+ currentMutable.UnregisterCurrent();
+ type.Should().Be(typeof(IDummyInterface));
+ contract.Should().BeNull();
+ unregisterAllCalled.Should().BeTrue();
+
+ unregisterAllCalled = false;
+ currentMutable.UnregisterCurrent("test");
+ type.Should().Be(typeof(IEnableLogger));
+ contract.Should().Be("test");
+ unregisterAllCalled.Should().BeTrue();
+ }
+ }
+}
diff --git a/src/Splat.Tests/ServiceLocation/BaseDependencyResolverTests.cs b/src/Splat.Tests/ServiceLocation/BaseDependencyResolverTests.cs
index 1f4f036da..20516c2e6 100644
--- a/src/Splat.Tests/ServiceLocation/BaseDependencyResolverTests.cs
+++ b/src/Splat.Tests/ServiceLocation/BaseDependencyResolverTests.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using System.Text;
+using Splat.Common.Test;
using Splat.NLog;
using Xunit;
@@ -159,6 +160,57 @@ public void ILogManager_Resolvable()
Assert.NotNull(lm);
}
+ ///
+ /// Nulls the resolver tests.
+ ///
+ [Fact]
+ public void NullResolverTests()
+ {
+ IReadonlyDependencyResolver resolver = default;
+ IMutableDependencyResolver resolver1 = default;
+ IDependencyResolver resolver2 = default;
+ Assert.Throws(() => resolver.GetService());
+ Assert.Throws(() => resolver.GetServices());
+ Assert.Throws(() => resolver1.ServiceRegistrationCallback(typeof(ILogManager), (IDisposable d) => { d.Dispose(); }));
+ Assert.Throws(() => resolver2.WithResolver().Dispose());
+ Assert.Throws(() => resolver1.Register(() => new DefaultLogManager()));
+ Assert.Throws(() => resolver1.RegisterConstant(new DefaultLogManager()));
+ Assert.Throws(() => resolver1.RegisterLazySingleton(() => new DefaultLogManager(), typeof(ILogManager)));
+ Assert.Throws(() => resolver1.RegisterLazySingletonAnd(() => new DefaultLogManager(), typeof(ILogManager)));
+ Assert.Throws(() => resolver1.RegisterLazySingleton(() => new DefaultLogManager()));
+ Assert.Throws(() => resolver1.RegisterLazySingletonAnd("eight"));
+ Assert.Throws(() => resolver1.RegisterLazySingletonAnd(() => new DefaultLogManager(), "seven"));
+ Assert.Throws(() => resolver1.UnregisterCurrent());
+ Assert.Throws(() => resolver1.UnregisterAll());
+ Assert.Throws(() => resolver1.RegisterAnd());
+ Assert.Throws(() => resolver1.RegisterAnd(() => new DefaultLogManager()));
+ Assert.Throws(() => resolver1.RegisterAnd(() => new ViewModelOne()));
+ Assert.Throws(() => resolver1.Register());
+ Assert.Throws(() => resolver1.RegisterConstantAnd(new ViewModelOne()));
+ Assert.Throws(() => resolver1.RegisterConstantAnd(new ViewModelOne(), typeof(ViewModelOne)));
+ Assert.Throws(() => resolver1.RegisterConstantAnd());
+ }
+
+ ///
+ /// Registers the and tests.
+ ///
+ [Fact]
+ public void RegisterAndTests()
+ {
+ var resolver = GetDependencyResolver();
+ Assert.Throws(() => resolver.RegisterAnd(null));
+ resolver.RegisterAnd("one")
+ .RegisterAnd("two")
+ .RegisterAnd(() => new DefaultLogManager(), "three")
+ .RegisterAnd(() => new ViewModelOne(), "four")
+ .RegisterConstantAnd("five")
+ .RegisterConstantAnd(new ViewModelOne(), typeof(ViewModelOne), "six")
+ .RegisterLazySingletonAnd(() => new DefaultLogManager(), typeof(ILogManager), "seven")
+ .RegisterLazySingletonAnd("eight")
+ .RegisterLazySingletonAnd(() => new DefaultLogManager(), "seven")
+ .Register();
+ }
+
///
/// Gets an instance of a dependency resolver to test.
///
diff --git a/src/Splat.Tests/Splat.Tests.csproj b/src/Splat.Tests/Splat.Tests.csproj
index 88b9f9b32..18cfb75db 100644
--- a/src/Splat.Tests/Splat.Tests.csproj
+++ b/src/Splat.Tests/Splat.Tests.csproj
@@ -12,6 +12,7 @@
+
diff --git a/src/Splat/ServiceLocation/DependencyResolverMixins.cs b/src/Splat/ServiceLocation/DependencyResolverMixins.cs
index be913d30e..77a7714c4 100644
--- a/src/Splat/ServiceLocation/DependencyResolverMixins.cs
+++ b/src/Splat/ServiceLocation/DependencyResolverMixins.cs
@@ -115,6 +115,24 @@ public static void Register(this IMutableDependencyResolver resolver, Func
resolver.Register(() => factory(), typeof(T), contract);
}
+ ///
+ /// Registers a factory for the given .
+ ///
+ /// The type to register as.
+ /// The service type to register for.
+ /// The resolver to register the service type with.
+ /// A optional contract value which will indicates to only generate the value if this contract is specified.
+ public static void Register(this IMutableDependencyResolver resolver, string? contract = null)
+ where T : new()
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ resolver.Register(() => new T(), typeof(TAs), contract);
+ }
+
///
/// Registers a constant value which will always return the specified object instance.
///
diff --git a/src/Splat/ServiceLocation/FuncDependencyResolver.cs b/src/Splat/ServiceLocation/FuncDependencyResolver.cs
index 4b898ad4e..440c890a2 100644
--- a/src/Splat/ServiceLocation/FuncDependencyResolver.cs
+++ b/src/Splat/ServiceLocation/FuncDependencyResolver.cs
@@ -51,7 +51,7 @@ public FuncDependencyResolver(
///
public object? GetService(Type serviceType, string? contract = null)
{
- return (GetServices(serviceType, contract) ?? Enumerable.Empty()).LastOrDefault();
+ return (GetServices(serviceType, contract) ?? Array.Empty()).LastOrDefault();
}
///
diff --git a/src/Splat/ServiceLocation/ModernDependencyResolver.cs b/src/Splat/ServiceLocation/ModernDependencyResolver.cs
index a4cdece1b..1515c06f7 100644
--- a/src/Splat/ServiceLocation/ModernDependencyResolver.cs
+++ b/src/Splat/ServiceLocation/ModernDependencyResolver.cs
@@ -133,13 +133,13 @@ public IEnumerable GetServices(Type serviceType, string? contract = null
{
if (_registry is null)
{
- return Enumerable.Empty();
+ return Array.Empty();
}
var pair = GetKey(serviceType, contract);
if (!_registry.ContainsKey(pair))
{
- return Enumerable.Empty();
+ return Array.Empty();
}
return _registry[pair].Select(x => x()).ToList();
diff --git a/src/Splat/ServiceLocation/ResolverMixins.cs b/src/Splat/ServiceLocation/ResolverMixins.cs
new file mode 100644
index 000000000..4f9265c50
--- /dev/null
+++ b/src/Splat/ServiceLocation/ResolverMixins.cs
@@ -0,0 +1,223 @@
+// 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.Threading;
+
+namespace Splat
+{
+ ///
+ /// Resolver Mixins.
+ ///
+ public static class ResolverMixins
+ {
+ ///
+ /// Registers a factory for the given .
+ ///
+ /// The service type to register for.
+ /// The resolver to register the service type with.
+ /// A optional contract value which will indicates to only generate the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterAnd(this IMutableDependencyResolver resolver, string? contract = null)
+ where T : new()
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ resolver.Register(() => new T(), typeof(T), contract);
+ return resolver;
+ }
+
+ ///
+ /// Registers a factory for the given .
+ ///
+ /// The service type to register for.
+ /// The resolver to register the service type with.
+ /// A factory method for generating a object of the specified type.
+ /// A optional contract value which will indicates to only generate the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterAnd(this IMutableDependencyResolver resolver, Func factory, string? contract = null)
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ if (factory is null)
+ {
+ throw new ArgumentNullException(nameof(factory));
+ }
+
+ resolver.Register(() => factory()!, typeof(T), contract);
+ return resolver;
+ }
+
+ ///
+ /// Registers a factory for the given .
+ ///
+ /// The type to register as.
+ /// The service type to register for.
+ /// The resolver to register the service type with.
+ /// A optional contract value which will indicates to only generate the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterAnd(this IMutableDependencyResolver resolver, string? contract = null)
+ where T : new()
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ resolver.Register(() => new T(), typeof(TAs), contract);
+ return resolver;
+ }
+
+ ///
+ /// Registers a factory for the given .
+ ///
+ /// The type to register as.
+ /// The service type to register for.
+ /// The resolver to register the service type with.
+ /// A factory method for generating a object of the specified type.
+ /// A optional contract value which will indicates to only generate the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterAnd(this IMutableDependencyResolver resolver, Func factory, string? contract = null)
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ if (factory is null)
+ {
+ throw new ArgumentNullException(nameof(factory));
+ }
+
+ resolver.Register(() => factory()!, typeof(TAs), contract);
+ return resolver;
+ }
+
+ ///
+ /// Registers a constant value which will always return the specified object instance.
+ ///
+ /// The resolver to register the service type with.
+ /// The specified instance to always return.
+ /// The type of service to register.
+ /// A optional contract value which will indicates to only return the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterConstantAnd(this IMutableDependencyResolver resolver, object value, Type serviceType, string? contract = null)
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ resolver.Register(() => value, serviceType, contract);
+ return resolver;
+ }
+
+ ///
+ /// Registers a constant value which will always return the specified object instance.
+ ///
+ /// The service type to register for.
+ /// The resolver to register the service type with.
+ /// A optional contract value which will indicates to only return the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterConstantAnd(this IMutableDependencyResolver resolver, string? contract = null)
+ where T : new()
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ var value = new T();
+ return resolver.RegisterAnd(() => value, contract);
+ }
+
+ ///
+ /// Registers a constant value which will always return the specified object instance.
+ ///
+ /// The service type to register for.
+ /// The resolver to register the service type with.
+ /// The specified instance to always return.
+ /// A optional contract value which will indicates to only return the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterConstantAnd(this IMutableDependencyResolver resolver, T value, string? contract = null)
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ return resolver.RegisterAnd(() => value, contract);
+ }
+
+ ///
+ /// Registers a lazy singleton value which will always return the specified object instance once created.
+ /// The value is only generated once someone requests the service from the resolver.
+ ///
+ /// The resolver to register the service type with.
+ /// A factory method for generating a object of the specified type.
+ /// The type of service to register.
+ /// A optional contract value which will indicates to only return the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterLazySingletonAnd(this IMutableDependencyResolver resolver, Func valueFactory, Type serviceType, string? contract = null)
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ var val = new Lazy(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication);
+ resolver.Register(() => val.Value, serviceType, contract);
+ return resolver;
+ }
+
+ ///
+ /// Registers a lazy singleton value which will always return the specified object instance once created.
+ /// The value is only generated once someone requests the service from the resolver.
+ ///
+ /// The service type to register for.
+ /// The resolver to register the service type with.
+ /// A optional contract value which will indicates to only return the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterLazySingletonAnd(this IMutableDependencyResolver resolver, string? contract = null)
+ where T : new()
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ var val = new Lazy(() => new T(), LazyThreadSafetyMode.ExecutionAndPublication);
+ resolver.Register(() => val.Value, typeof(T), contract);
+ return resolver;
+ }
+
+ ///
+ /// Registers a lazy singleton value which will always return the specified object instance once created.
+ /// The value is only generated once someone requests the service from the resolver.
+ ///
+ /// The service type to register for.
+ /// The resolver to register the service type with.
+ /// A factory method for generating a object of the specified type.
+ /// A optional contract value which will indicates to only return the value if this contract is specified.
+ /// The resolver.
+ public static IMutableDependencyResolver RegisterLazySingletonAnd(this IMutableDependencyResolver resolver, Func valueFactory, string? contract = null)
+ {
+ if (resolver is null)
+ {
+ throw new ArgumentNullException(nameof(resolver));
+ }
+
+ var val = new Lazy(() => valueFactory()!, LazyThreadSafetyMode.ExecutionAndPublication);
+ resolver.Register(() => val.Value, typeof(T), contract);
+ return resolver;
+ }
+ }
+}