Created
February 19, 2020 12:49
-
-
Save alistairjevans/e670568a7e929e815ee1591feef53e6f to your computer and use it in GitHub Desktop.
Single Registration Protections
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Autofac; | |
using Autofac.Core; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net.Http; | |
using Xunit; | |
namespace PreventDuplicateSingletons | |
{ | |
public class SingleRegistrationServices | |
{ | |
private static readonly HashSet<Type> servicesThatOnlyAllowOneRegistration = new HashSet<Type> | |
{ | |
typeof(HttpClient) | |
}; | |
private readonly HashSet<Type> servicesAlreadyRegistered = new HashSet<Type>(); | |
public void ServiceRegistered(object sender, ComponentRegisteredEventArgs e) | |
{ | |
// Get the typed services in the registration. | |
var typedServices = e.ComponentRegistration.Services.OfType<TypedService>(); | |
foreach (var service in typedServices) | |
{ | |
// Is this service type in our list of 'protected' types? | |
if(servicesThatOnlyAllowOneRegistration.Contains(service.ServiceType)) | |
{ | |
// If we cannot add it to the set we've already registered, | |
// it means we have already seen it. | |
if(!servicesAlreadyRegistered.Add(service.ServiceType)) | |
{ | |
throw new InvalidOperationException($"Detected invalid double-registration of {service.ServiceType.Name}"); | |
} | |
} | |
} | |
} | |
} | |
public class PreventDuplicateServicesTests | |
{ | |
[Fact] | |
public void ThrowsOnDuplicateService() | |
{ | |
var builder = new ContainerBuilder(); | |
var singleAssertions = new SingleRegistrationServices(); | |
builder.RegisterCallback(regBuilder => regBuilder.Registered += singleAssertions.ServiceRegistered); | |
var httpClient1 = new HttpClient(); | |
var httpClient2 = new HttpClient(); | |
builder.RegisterInstance(httpClient1); | |
builder.RegisterInstance(httpClient2); | |
Assert.Throws<InvalidOperationException>(() => | |
{ | |
builder.Build(); | |
}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment