Skip to content

Commit

Permalink
Merge pull request #940 from eugbaranov/feature/source-registrar
Browse files Browse the repository at this point in the history
Registration source registration consistent with module registration
  • Loading branch information
tillig committed Nov 1, 2018
2 parents 426c3ee + ac16101 commit e7c821c
Show file tree
Hide file tree
Showing 5 changed files with 298 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/Autofac/Core/Registration/ISourceRegistrar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// This software is part of the Autofac IoC container
// Copyright © 2018 Autofac Contributors
// http://autofac.org
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

namespace Autofac.Core.Registration
{
/// <summary>
/// Interface providing fluent syntax for chaining registration source registrations.
/// </summary>
public interface ISourceRegistrar
{
/// <summary>
/// Add a registration source to the container.
/// </summary>
/// <param name="registrationSource">The registration source to add.</param>
/// <returns>
/// The <see cref="ISourceRegistrar"/> to allow additional chained registration source registrations.
/// </returns>
ISourceRegistrar RegisterSource(IRegistrationSource registrationSource);
}
}
74 changes: 74 additions & 0 deletions src/Autofac/Core/Registration/SourceRegistrar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// This software is part of the Autofac IoC container
// Copyright © 2018 Autofac Contributors
// http://autofac.org
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

using System;

namespace Autofac.Core.Registration
{
/// <summary>
/// Basic implementation of the <see cref="ISourceRegistrar"/>
/// interface allowing registration of registration sources into a <see cref="ContainerBuilder"/>
/// in a fluent format.
/// </summary>
internal sealed class SourceRegistrar : ISourceRegistrar
{
/// <summary>
/// The <see cref="ContainerBuilder"/> into which registrations will be made.
/// </summary>
private readonly ContainerBuilder _builder;

/// <summary>
/// Initializes a new instance of the <see cref="SourceRegistrar"/> class.
/// </summary>
/// <param name="builder">
/// The <see cref="ContainerBuilder"/> into which registrations will be made.
/// </param>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="builder" /> is <see langword="null" />.
/// </exception>
public SourceRegistrar(ContainerBuilder builder)
{
_builder = builder ?? throw new ArgumentNullException(nameof(builder));
}

/// <summary>
/// Add a registration source to the container.
/// </summary>
/// <param name="registrationSource">The registration source to add.</param>
/// <returns>
/// The <see cref="ISourceRegistrar"/> to allow additional chained registration source registrations.
/// </returns>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="registrationSource" /> is <see langword="null" />.
/// </exception>
public ISourceRegistrar RegisterSource(IRegistrationSource registrationSource)
{
if (registrationSource == null) throw new ArgumentNullException(nameof(registrationSource));

_builder.RegisterCallback(cr => cr.AddRegistrationSource(registrationSource));
return this;
}
}
}
76 changes: 76 additions & 0 deletions src/Autofac/SourceRegistrationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// This software is part of the Autofac IoC container
// Copyright © 2018 Autofac Contributors
// http://autofac.org
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

using System;
using Autofac.Core;
using Autofac.Core.Registration;

namespace Autofac
{
/// <summary>
/// Extension methods for registering <see cref="IRegistrationSource"/> instances with a container.
/// </summary>
public static class SourceRegistrationExtensions
{
/// <summary>
/// Add a registration source to the container.
/// </summary>
/// <param name="builder">The builder to register the registration source with.</param>
/// <typeparam name="TRegistrationSource">The registration source to add.</typeparam>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="builder"/> is <see langword="null"/>.
/// </exception>
/// <returns>
/// The <see cref="ISourceRegistrar"/> to allow additional chained registration source registrations.
/// </returns>
public static ISourceRegistrar RegisterSource<TRegistrationSource>(this ContainerBuilder builder)
where TRegistrationSource : IRegistrationSource, new()
{
if (builder == null) throw new ArgumentNullException(nameof(builder));

var registrar = new SourceRegistrar(builder);
return registrar.RegisterSource<TRegistrationSource>();
}

/// <summary>
/// Add a registration source to the container.
/// </summary>
/// <param name="registrar">The source registrar that will make the registration into the container.</param>
/// <typeparam name="TRegistrationSource">The registration source to add.</typeparam>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="registrar"/> is <see langword="null"/>.
/// </exception>
/// <returns>
/// The <see cref="ISourceRegistrar"/> to allow additional chained registration source registrations.
/// </returns>
public static ISourceRegistrar RegisterSource<TRegistrationSource>(this ISourceRegistrar registrar)
where TRegistrationSource : IRegistrationSource, new()
{
if (registrar == null) throw new ArgumentNullException(nameof(registrar));

return registrar.RegisterSource(new TRegistrationSource());
}
}
}
50 changes: 50 additions & 0 deletions test/Autofac.Test/Core/Registration/SourceRegistrarTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using Autofac.Core.Registration;
using Autofac.Test.Scenarios.RegistrationSources;
using Xunit;

namespace Autofac.Test.Core.Registration
{
public sealed class SourceRegistrarTests
{
private static readonly object O1 = new object();
private static readonly object O2 = new object();

[Fact]
public void Ctor_RequiresContainerBuilder()
{
Assert.Throws<ArgumentNullException>(() => new SourceRegistrar(null));
}

[Fact]
public void RegisterSource_ChainsSourceRegistrations()
{
var builder = new ContainerBuilder();
var registrar = new SourceRegistrar(builder);

registrar.RegisterSource<SourceA>()
.RegisterSource(new ObjectRegistrationSource(O2));

var container = builder.Build();
var objects = container.Resolve<IEnumerable<object>>();
Assert.Contains(O1, objects);
Assert.Contains(O2, objects);
}

[Fact]
public void RegisterSource_RequiresRegistrationSource()
{
var registrar = new SourceRegistrar(new ContainerBuilder());
Assert.Throws<ArgumentNullException>(() => registrar.RegisterSource(null));
}

private class SourceA : ObjectRegistrationSource
{
public SourceA()
: base(O1)
{
}
}
}
}
56 changes: 56 additions & 0 deletions test/Autofac.Test/SourceRegistrationExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Autofac.Core;
using Autofac.Test.Scenarios.RegistrationSources;
using Xunit;

namespace Autofac.Test
{
public sealed class SourceRegistrationExtensionsTests
{
[Fact]
public void RegisterSource()
{
var source = new EmptyRegistrationSource();
var builder = new ContainerBuilder();

builder.RegisterSource(source);

Assert.False(source.RegistrationsForCalled);
using (var container = builder.Build())
{
Assert.True(source.RegistrationsForCalled);
}

new ObjectRegistrationSource();
}

[Fact]
public void RegisterObjectSource()
{
var builder = new ContainerBuilder();

builder.RegisterSource<ObjectRegistrationSource>();

using (var container = builder.Build())
{
var service = container.Resolve<object>();
Assert.NotNull(service);
}
}

private sealed class EmptyRegistrationSource : IRegistrationSource
{
public bool RegistrationsForCalled { get; private set; }

public bool IsAdapterForIndividualComponents => false;

public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
RegistrationsForCalled = true;
return Enumerable.Empty<IComponentRegistration>();
}
}
}
}

0 comments on commit e7c821c

Please sign in to comment.