Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/Autofac.Extras.AttributeMetadata/AutofacAttributeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,40 @@ public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistr

return builder;
}

/// <summary>
/// Registers metadata that is declared loosely using attributes marked with the
/// MetadataAttributeAttribute for an individual type registration. All of the marked
/// attributes are used together to create a common set of dictionary values that
/// constitute the metadata on the type.
/// </summary>
/// <typeparam name="TLimit">The type of the registration limit.</typeparam>
/// <param name="builder">The registration builder containing registration data.</param>
/// <returns>Registration builder allowing the registration to be configured.</returns>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="builder" /> is <see langword="null" />.
/// </exception>
/// <remarks>
/// <para>
/// This is the individual registration counterpart to the assembly scanning overload, so
/// <c>RegisterType</c> and <c>RegisterAssemblyTypes</c> can both opt in to attributed metadata
/// the same way. It applies to reflection-based registrations, where the implementation type is
/// known at registration time; for delegate registrations, use the
/// <see cref="AttributedMetadataModule"/> instead.
/// </para>
/// <para>
/// This can safely be combined with the <see cref="AttributedMetadataModule"/>. The module does
/// not overwrite metadata keys that are already present, so metadata is applied once.
/// </para>
/// </remarks>
public static IRegistrationBuilder<TLimit, ConcreteReflectionActivatorData, SingleRegistrationStyle>
WithAttributedMetadata<TLimit>(this IRegistrationBuilder<TLimit, ConcreteReflectionActivatorData, SingleRegistrationStyle> builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}

return builder.WithMetadata(MetadataHelper.GetMetadata(builder.ActivatorData.ImplementationType));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) Autofac Project. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System.Reflection;
using Autofac.Builder;
using Autofac.Extras.AttributeMetadata.Test.ScenarioTypes.WeakTypedMetadataAttributeScenario;
using Autofac.Features.Metadata;

namespace Autofac.Extras.AttributeMetadata.Test;

public class SingleRegistrationAttributedMetadataTestFixture
{
[Fact]
public void Validate_attributed_metadata_on_generic_type_registration()
{
// arrange
var builder = new ContainerBuilder();
builder.RegisterType<WeakTypedScenario>().As<IWeakTypedScenario>().WithAttributedMetadata();

// act
var item = builder.Build().Resolve<Meta<IWeakTypedScenario>>();

// assert
Assert.Equal("Hello", item.Metadata["Name"]);
}

[Fact]
public void Validate_attributed_metadata_on_non_generic_type_registration()
{
// arrange
var builder = new ContainerBuilder();
builder.RegisterType(typeof(WeakTypedScenario)).As<IWeakTypedScenario>().WithAttributedMetadata();

// act
var item = builder.Build().Resolve<Meta<IWeakTypedScenario>>();

// assert
Assert.Equal("Hello", item.Metadata["Name"]);
}

[Fact]
public void Validate_assembly_scanning_registration_still_resolves()
{
// arrange
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.As<IWeakTypedScenario>()
.WithAttributedMetadata();

// act
var item = builder.Build().Resolve<Meta<IWeakTypedScenario>>();

// assert
Assert.Equal("Hello", item.Metadata["Name"]);
}

[Fact]
public void Validate_no_conflict_when_combined_with_attributed_metadata_module()
{
// arrange
var builder = new ContainerBuilder();
builder.RegisterModule<AttributedMetadataModule>();
builder.RegisterType<WeakTypedScenario>().As<IWeakTypedScenario>().WithAttributedMetadata();

// act
var item = builder.Build().Resolve<Meta<IWeakTypedScenario>>();

// assert
Assert.Equal("Hello", item.Metadata["Name"]);
}

[Fact]
public void Validate_null_builder_throws()
{
// arrange
IRegistrationBuilder<WeakTypedScenario, ConcreteReflectionActivatorData, SingleRegistrationStyle> builder = null!;

// act / assert
Assert.Throws<ArgumentNullException>(() => { builder.WithAttributedMetadata(); });
}
}
Loading