Skip to content

Commit

Permalink
Fixed #730: Added MatchingLifetimeScopeTags() extension to IComponent…
Browse files Browse the repository at this point in the history
…Registration to get scope tags.
  • Loading branch information
tillig committed Apr 25, 2017
1 parent 2feea40 commit 6261d4b
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 5 deletions.
42 changes: 42 additions & 0 deletions src/Autofac/Core/ComponentRegistrationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Autofac.Core.Lifetime;

namespace Autofac.Core
{
/// <summary>
/// Extension methods for <see cref="IComponentRegistration"/>.
/// </summary>
public static class ComponentRegistrationExtensions
{
/// <summary>
/// For components registered instance-per-matching-lifetime-scope, retrieves the set
/// of lifetime scope tags to match.
/// </summary>
/// <param name="registration">
/// The <see cref="IComponentRegistration"/> to query for matching lifetime scope tags.
/// </param>
/// <returns>
/// If the component is registered instance-per-matching-lifetime-scope, this method returns
/// the set of matching lifetime scope tags. If the component is singleton, instance-per-scope,
/// instance-per-dependency, or otherwise not an instance-per-matching-lifetime-scope
/// component, this method returns an empty enumeration.
/// </returns>
public static IEnumerable<object> MatchingLifetimeScopeTags(this IComponentRegistration registration)
{
if (registration == null)
{
throw new ArgumentNullException(nameof(registration));
}

var lifetime = registration.Lifetime as MatchingScopeLifetime;
if (lifetime != null)
{
return lifetime.TagsToMatch;
}

return Enumerable.Empty<object>();
}
}
}
34 changes: 29 additions & 5 deletions src/Autofac/Core/Lifetime/MatchingScopeLifetime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

Expand All @@ -42,9 +43,27 @@ public class MatchingScopeLifetime : IComponentLifetime
/// <param name="lifetimeScopeTagsToMatch">The tags applied to matching scopes.</param>
public MatchingScopeLifetime(params object[] lifetimeScopeTagsToMatch)
{
if (lifetimeScopeTagsToMatch == null) throw new ArgumentNullException(nameof(lifetimeScopeTagsToMatch));
if (lifetimeScopeTagsToMatch == null)
{
throw new ArgumentNullException(nameof(lifetimeScopeTagsToMatch));
}

_tagsToMatch = lifetimeScopeTagsToMatch;
this._tagsToMatch = lifetimeScopeTagsToMatch;
}

/// <summary>
/// Gets the list of lifetime scope tags to match.
/// </summary>
/// <value>
/// An <see cref="IEnumerable{T}"/> of object tags to match
/// when searching for the lifetime scope for the component.
/// </value>
public IEnumerable<object> TagsToMatch
{
get
{
return this._tagsToMatch;
}
}

/// <summary>
Expand All @@ -55,19 +74,24 @@ public MatchingScopeLifetime(params object[] lifetimeScopeTagsToMatch)
/// <returns>The scope for the component.</returns>
public ISharingLifetimeScope FindScope(ISharingLifetimeScope mostNestedVisibleScope)
{
if (mostNestedVisibleScope == null) throw new ArgumentNullException(nameof(mostNestedVisibleScope));
if (mostNestedVisibleScope == null)
{
throw new ArgumentNullException(nameof(mostNestedVisibleScope));
}

var next = mostNestedVisibleScope;
while (next != null)
{
if (_tagsToMatch.Contains(next.Tag))
if (this._tagsToMatch.Contains(next.Tag))
{
return next;
}

next = next.ParentLifetimeScope;
}

throw new DependencyResolutionException(string.Format(
CultureInfo.CurrentCulture, MatchingScopeLifetimeResources.MatchingScopeNotFound, string.Join(", ", _tagsToMatch)));
CultureInfo.CurrentCulture, MatchingScopeLifetimeResources.MatchingScopeNotFound, string.Join(", ", this._tagsToMatch)));
}
}
}
60 changes: 60 additions & 0 deletions test/Autofac.Test/Core/ComponentRegistrationExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using Autofac.Core;
using Xunit;

namespace Autofac.Test.Core
{
public class ComponentRegistrationExtensionsTests
{
[Fact]
public void MatchingLifetimeScopeTags_InstancePerDependency()
{
var b = new ContainerBuilder();
b.RegisterType<DivideByZeroException>().InstancePerDependency();
var c = b.Build();
Assert.Empty(c.RegistrationFor<DivideByZeroException>().MatchingLifetimeScopeTags());
}

[Fact]
public void MatchingLifetimeScopeTags_InstancePerLifetimeScope()
{
var b = new ContainerBuilder();
b.RegisterType<DivideByZeroException>().InstancePerLifetimeScope();
var c = b.Build();
Assert.Empty(c.RegistrationFor<DivideByZeroException>().MatchingLifetimeScopeTags());
}

[Fact]
public void MatchingLifetimeScopeTags_InstancePerMatchingLifetimeScope_Multiple()
{
var b = new ContainerBuilder();
b.RegisterType<DivideByZeroException>().InstancePerMatchingLifetimeScope("tag1", "tag2");
var c = b.Build();
Assert.Equal(new object[] { "tag1", "tag2" }, c.RegistrationFor<DivideByZeroException>().MatchingLifetimeScopeTags());
}

[Fact]
public void MatchingLifetimeScopeTags_InstancePerMatchingLifetimeScope_Single()
{
var b = new ContainerBuilder();
b.RegisterType<DivideByZeroException>().InstancePerMatchingLifetimeScope("tag1");
var c = b.Build();
Assert.Equal(new object[] { "tag1" }, c.RegistrationFor<DivideByZeroException>().MatchingLifetimeScopeTags());
}

[Fact]
public void MatchingLifetimeScopeTags_NullRegistration()
{
Assert.Throws<ArgumentNullException>(() => ComponentRegistrationExtensions.MatchingLifetimeScopeTags(null));
}

[Fact]
public void MatchingLifetimeScopeTags_Singleton()
{
var b = new ContainerBuilder();
b.RegisterType<DivideByZeroException>().SingleInstance();
var c = b.Build();
Assert.Empty(c.RegistrationFor<DivideByZeroException>().MatchingLifetimeScopeTags());
}
}
}

0 comments on commit 6261d4b

Please sign in to comment.