Skip to content

Commit

Permalink
added functionality for registering factories and changing scope.
Browse files Browse the repository at this point in the history
  • Loading branch information
ffMathy committed Jun 12, 2019
1 parent ae69ce5 commit 3cba692
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 22 deletions.
Expand Up @@ -8,7 +8,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
</ItemGroup>
Expand Down
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace FluffySpoon.Extensions.MicrosoftDependencyInjection.Tests
{
Expand All @@ -10,7 +11,11 @@ public class RegistrationTest
public void CanRegisterGenericTypes()
{
var services = new ServiceCollection();
services.AddAssemblyTypesAsImplementedInterfaces(typeof(RegistrationTest).Assembly);
services.AddAssemblyTypesAsImplementedInterfaces(new RegistrationSettings() {
Assemblies = new [] {
typeof(RegistrationTest).Assembly
}
});

var container = services.BuildServiceProvider();

Expand All @@ -22,12 +27,37 @@ public void CanRegisterGenericTypes()
public void CanRegisterGenericClassWithNoGenericInterface()
{
var services = new ServiceCollection();
services.AddAssemblyTypesAsImplementedInterfaces(typeof(RegistrationTest).Assembly);
services.AddAssemblyTypesAsImplementedInterfaces(new RegistrationSettings()
{
Assemblies = new[] {
typeof(RegistrationTest).Assembly
}
});

var container = services.BuildServiceProvider();

var instance = container.GetService<INonGeneric>();
Assert.IsNull(instance);
}

[TestMethod]
public void CanRegisterFactories()
{
var services = new ServiceCollection();

var registrationSettings = new RegistrationSettings()
{
Assemblies = new[] {
typeof(RegistrationTest).Assembly
}
};
services.AddAssemblyTypesAsImplementedInterfaces(registrationSettings);
services.AddAssemblyTypesAsFactories(registrationSettings);

var container = services.BuildServiceProvider();

var instance = container.GetService<Func<IGenericWrapper>>()();
Assert.IsNotNull(instance);
}
}
}
Expand Up @@ -6,10 +6,56 @@
namespace FluffySpoon.Extensions.MicrosoftDependencyInjection
{
public static class RegistrationExtensions
{
public static void AddAssemblyTypesAsImplementedInterfaces(
this IServiceCollection serviceCollection,
RegistrationSettings settings)
{
private delegate ServiceDescriptor GetServiceDescriptorDelegate(
Type interfaceType,
Type implementationType);

public static void AddAssemblyTypesAsImplementedInterfaces(
this IServiceCollection serviceCollection,
RegistrationSettings settings)
{
AddAssemblyTypesAsImplementedInterfaces(
serviceCollection,
settings,
(interfaceType, implementationType) =>
new ServiceDescriptor(
interfaceType,
implementationType,
settings.Scope ?? ServiceLifetime.Scoped));
}

public static void AddAssemblyTypesAsFactories(
this IServiceCollection serviceCollection,
RegistrationSettings settings)
{
AddAssemblyTypesAsImplementedInterfaces(
serviceCollection,
settings,
(interfaceType, implementationType) => {
var interfaceFuncType = typeof(Func<>).MakeGenericType(interfaceType);
var serviceProviderExtensionsType = typeof(ServiceProviderServiceExtensions);
var serviceProviderExtensionsGetServiceMethod = serviceProviderExtensionsType
.GetMethods()
.Single(x =>
x.Name == nameof(ServiceProviderServiceExtensions.GetRequiredService) &&
x.IsGenericMethod)
.MakeGenericMethod(interfaceType);
return new ServiceDescriptor(
interfaceFuncType,
provider => Delegate.CreateDelegate(
interfaceFuncType,
provider,
serviceProviderExtensionsGetServiceMethod),
settings.Scope ?? ServiceLifetime.Singleton);
});
}

private static void AddAssemblyTypesAsImplementedInterfaces(
IServiceCollection serviceCollection,
RegistrationSettings settings,
GetServiceDescriptorDelegate getServiceDescriptor)
{
foreach (var assembly in settings.Assemblies)
{
Expand Down Expand Up @@ -37,9 +83,10 @@ public static class RegistrationExtensions
if (implementationType.IsGenericType && interfaceType.IsGenericType)
interfaceType = interfaceType.GetGenericTypeDefinition();

serviceCollection.AddScoped(
interfaceType,
implementationType);
var descriptor = getServiceDescriptor(
interfaceType,
implementationType);
serviceCollection.Add(descriptor);
}
} catch(Exception ex) {
throw new Exception("Could not load type " + classType.FullName, ex);
Expand All @@ -56,14 +103,5 @@ public static class RegistrationExtensions
(type.Namespace != null &&
settings.Filter(type));
}

public static void AddAssemblyTypesAsImplementedInterfaces(
this IServiceCollection serviceCollection,
params Assembly[] assemblies)
{
AddAssemblyTypesAsImplementedInterfaces(serviceCollection, new RegistrationSettings() {
Assemblies = assemblies
});
}
}
}
@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
Expand All @@ -9,11 +10,14 @@ public class RegistrationSettings
{
public Func<Type, bool> Filter { get; set; }

public IEnumerable<Assembly> Assemblies { get; set; }
public ServiceLifetime? Scope { get; set; }

public IEnumerable<Assembly> Assemblies { get; set; }

public RegistrationSettings()
{
Assemblies = new List<Assembly>();
}
Scope = ServiceLifetime.Scoped;
}
}
}

0 comments on commit 3cba692

Please sign in to comment.