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

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Autofac Project. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Autofac.Core;
using Autofac.Extras.AttributeMetadata.Test.Stubs;
using Autofac.Features.Metadata;

namespace Autofac.Extras.AttributeMetadata.Test;

public class AttributedMetadataModuleTests
{
[Fact]
public void AttachToComponentRegistration_NestedLifetimeScope()
{
// A child scope sees parent registrations wrapped in registrations that share the parent's
// metadata dictionary, so the module must not attempt to add the same keys twice.
var builder = new ContainerBuilder();
builder.RegisterModule<AttributedMetadataModule>();
builder.RegisterType<NestedScopeComponent>().As<INestedScopeComponent>();
var container = builder.Build();

using var lifetimeScope = container.BeginLifetimeScope(x => x.RegisterType<NestedScopeComponent>());
var exception = Record.Exception(() => lifetimeScope.Resolve<Meta<INestedScopeComponent>>());

Assert.Null(exception);
}

[Fact]
public void AttachToComponentRegistration_NullRegistration()
{
var module = new AttachableMetadataModule();

Assert.Throws<ArgumentNullException>(() => module.Attach(null!));
}

/// <summary>
/// Exposes the protected attachment point so the argument guard can be exercised directly.
/// </summary>
private sealed class AttachableMetadataModule : AttributedMetadataModule
{
public void Attach(IComponentRegistration registration) => AttachToComponentRegistration(null!, registration);
}

private interface INestedScopeComponent
{
}

[Data("ParentLifetime")]
private sealed class NestedScopeComponent : INestedScopeComponent
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// 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.Stubs;
using Autofac.Features.Metadata;
using Autofac.Features.Scanning;
using Autofac.Integration.Mef;

namespace Autofac.Extras.AttributeMetadata.Test;

public class AutofacAttributeExtensionsTests
{
[Fact]
public void WithAttributedMetadata_AssemblyScanningBuilder()
{
// The single registration overload must not make the assembly scanning overload ambiguous.
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.As<IReflectedComponent>()
.WithAttributedMetadata();

var item = builder.Build().Resolve<Meta<IReflectedComponent>>();

Assert.Equal("Hello", item.Metadata["Data"]);
}

[Fact]
public void WithAttributedMetadata_GenericTypeRegistration()
{
var builder = new ContainerBuilder();
builder.RegisterType<ReflectedComponent>().As<IReflectedComponent>().WithAttributedMetadata();

var item = builder.Build().Resolve<Meta<IReflectedComponent>>();

Assert.Equal("Hello", item.Metadata["Data"]);
}

[Fact]
public void WithAttributedMetadata_NonGenericTypeRegistration()
{
var builder = new ContainerBuilder();
builder.RegisterType(typeof(ReflectedComponent)).As<IReflectedComponent>().WithAttributedMetadata();

var item = builder.Build().Resolve<Meta<IReflectedComponent>>();

Assert.Equal("Hello", item.Metadata["Data"]);
}

[Fact]
public void WithAttributedMetadata_NullScanningBuilder()
{
IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle> builder = null!;

Assert.Throws<ArgumentNullException>(() => { builder.WithAttributedMetadata(); });
}

[Fact]
public void WithAttributedMetadata_NullSingleRegistrationBuilder()
{
IRegistrationBuilder<ReflectedComponent, ConcreteReflectionActivatorData, SingleRegistrationStyle> builder = null!;

Assert.Throws<ArgumentNullException>(() => { builder.WithAttributedMetadata(); });
}

[Fact]
public void WithAttributedMetadata_NullTypedViewBuilder()
{
IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle> builder = null!;

Assert.Throws<ArgumentNullException>(() => { builder.WithAttributedMetadata<IDataAndCountView>(); });
}

[Fact]
public void WithAttributedMetadata_TypedViewAssemblyScanning()
{
var builder = new ContainerBuilder();
builder.RegisterMetadataRegistrationSources();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.As<ITypedComponent>()
.WithAttributedMetadata<IDataAndCountView>();

var items = builder.Build().Resolve<IEnumerable<Lazy<ITypedComponent, IDataAndCountView>>>();

Assert.Single(items, p => p.Metadata.Data == "Hello" && p.Metadata.Count == 42);
}

[Fact]
public void WithAttributedMetadata_WithAttributedMetadataModule()
{
// The module skips keys that are already present, so metadata is applied once even though
// both the module and the extension target the same registration.
var builder = new ContainerBuilder();
builder.RegisterModule<AttributedMetadataModule>();
builder.RegisterType<ReflectedComponent>().As<IReflectedComponent>().WithAttributedMetadata();

var item = builder.Build().Resolve<Meta<IReflectedComponent>>();

Assert.Equal("Hello", item.Metadata["Data"]);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// 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.Extras.AttributeMetadata.Test.Stubs;
using Autofac.Integration.Mef;

namespace Autofac.Extras.AttributeMetadata.Test.Integration;

public class AssemblyScanningTests
{
[Fact]
public void MetadataFromCombinedAttributes()
{
// Two separate reflected attributes merge into a single metadata view.
var items = ScanFor<ICombinedComponent, IDataAndCountView>();

Assert.Single(items);
Assert.Single(items, p => p.Metadata.Data == "Hello" && p.Metadata.Count == 42);
}

[Fact]
public void MetadataFromReflectedAttribute()
{
var items = ScanFor<IReflectedComponent, IDataView>();

Assert.Single(items);
Assert.Single(items, p => p.Metadata.Data == "Hello");
}

[Fact]
public void MetadataFromTypedAttribute()
{
// Because the attribute implements the view, the typed overload can pick it out by view type.
var builder = new ContainerBuilder();
builder.RegisterMetadataRegistrationSources();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.As<ITypedComponent>()
.WithAttributedMetadata<IDataAndCountView>();

var items = builder.Build().Resolve<IEnumerable<Lazy<ITypedComponent, IDataAndCountView>>>().ToList();

Assert.Equal(2, items.Count);
Assert.IsType<TypedComponent>(items.First(p => p.Metadata.Data == "Hello" && p.Metadata.Count == 42).Value);
Assert.IsType<AlternateTypedComponent>(items.First(p => p.Metadata.Data == "Goodbye" && p.Metadata.Count == 24).Value);
}

private static List<Lazy<TService, TView>> ScanFor<TService, TView>()
where TService : notnull
{
var builder = new ContainerBuilder();
builder.RegisterMetadataRegistrationSources();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.As<TService>()
.WithAttributedMetadata();

return builder.Build().Resolve<IEnumerable<Lazy<TService, TView>>>().ToList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Autofac Project. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Autofac.Extras.AttributeMetadata.Test.Stubs;
using Autofac.Integration.Mef;

namespace Autofac.Extras.AttributeMetadata.Test.Integration;

public class AttributedMetadataModuleTests
{
[Fact]
public void MetadataFromCombinedAttributes()
{
var builder = new ContainerBuilder();
builder.RegisterModule(new ScanningModule());

var component = builder.Build().Resolve<Lazy<ICombinedComponent, IDataAndCountView>>();

Assert.Equal("Hello", component.Metadata.Data);
Assert.Equal(42, component.Metadata.Count);
}

[Fact]
public void MetadataFromReflectedAttribute()
{
var builder = new ContainerBuilder();
builder.RegisterModule(new ScanningModule());

var component = builder.Build().Resolve<Lazy<IReflectedComponent, IDataView>>();

Assert.Equal("Hello", component.Metadata.Data);
}

/// <summary>
/// Registers components without declaring any metadata, leaving the base module to pick the
/// metadata up off their attributes.
/// </summary>
private sealed class ScanningModule : AttributedMetadataModule
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterMetadataRegistrationSources();
builder.RegisterType<ReflectedComponent>().As<IReflectedComponent>();
builder.RegisterType<CombinedComponent>().As<ICombinedComponent>();
}
}
}
Loading
Loading