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
1 change: 1 addition & 0 deletions AppCoreNet.Extensions.sln
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
stylecop.json = stylecop.json
Directory.Packages.props = Directory.Packages.props
NuGet.config = NuGet.config
renovate.json = renovate.json
EndProjectSection
EndProject
Global
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright (c) The AppCore .NET project.

using System;
using System.Diagnostics.CodeAnalysis;
using AppCoreNet.Diagnostics;

namespace AppCoreNet.Extensions.DependencyInjection.Activator;
Expand All @@ -19,7 +20,9 @@ public static class ActivatorExtensions
/// <param name="parameters">Constructor arguments not provided by the <see cref="IServiceProvider"/>.</param>
/// <returns>An activated object of type <typeparamref name="T"/>.</returns>
/// <exception cref="ArgumentNullException">Argument <paramref name="activator"/> is null.</exception>
public static T? CreateInstance<T>(this IActivator activator, params object[] parameters)
public static T? CreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(
this IActivator activator,
params object[] parameters)
{
Ensure.Arg.NotNull(activator);
return (T?)activator.CreateInstance(typeof(T), parameters);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright (c) The AppCore .NET project.

using System;
using System.Diagnostics.CodeAnalysis;
using AppCoreNet.Diagnostics;

namespace AppCoreNet.Extensions.DependencyInjection.Activator;
Expand All @@ -17,7 +18,9 @@ public sealed class DefaultActivator : IActivator
public static DefaultActivator Instance { get; } = new();

/// <inheritdoc />
public object? CreateInstance(Type instanceType, params object[] parameters)
public object? CreateInstance(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType,
params object[] parameters)
{
Ensure.Arg.NotNull(instanceType);
Ensure.Arg.NotNull(parameters);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright (c) The AppCore .NET project.

using System;
using System.Diagnostics.CodeAnalysis;

namespace AppCoreNet.Extensions.DependencyInjection.Activator;

Expand All @@ -17,5 +18,7 @@ public interface IActivator
/// <param name="parameters">Constructor arguments not provided by the <see cref="IServiceProvider"/>.</param>
/// <returns>An activated object of type <paramref name="instanceType"/>.</returns>
/// <exception cref="ArgumentNullException">Argument <paramref name="instanceType"/> or <paramref name="parameters"/> is null.</exception>
object? CreateInstance(Type instanceType, params object[] parameters);
object? CreateInstance(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType,
params object[] parameters);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright (c) The AppCore .NET project.

using System;
using System.Diagnostics.CodeAnalysis;
using AppCoreNet.Diagnostics;
using Microsoft.Extensions.DependencyInjection;

Expand All @@ -26,7 +27,9 @@ public ServiceProviderActivator(IServiceProvider serviceProvider)
}

/// <inheritdoc />
public object? CreateInstance(Type instanceType, params object[] parameters)
public object? CreateInstance(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType,
params object[] parameters)
{
return ActivatorUtilities.CreateInstance(_serviceProvider, instanceType, parameters);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFrameworks>net8.0;netstandard2.0;net462</TargetFrameworks>
<RootNamespace>AppCoreNet.Extensions.DependencyInjection</RootNamespace>
<Description>Provides extensions to the Microsoft.Extensions.DependencyInjection framework.</Description>
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">true</IsAotCompatible>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright (c) The AppCore .NET project.

using System;
using System.Linq;
using System.Diagnostics.CodeAnalysis;
using AppCoreNet.Diagnostics;
using AppCoreNet.Extensions.DependencyInjection.Activator;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -12,7 +12,7 @@ namespace AppCoreNet.Extensions.DependencyInjection.Facilities;
/// <summary>
/// Provides a builder for facilities.
/// </summary>
public class FacilityBuilder
public sealed class FacilityBuilder
{
/// <summary>
/// Gets the <see cref="IServiceCollection"/>.
Expand All @@ -36,35 +36,23 @@ internal FacilityBuilder(IServiceCollection services, IActivator activator, Type
FacilityType = facilityType;
}

private IFacilityExtension<IFacility> CreateExtension(Type extensionType)
{
Type contractType = extensionType.GetInterfaces()
.First(i => i.GetGenericTypeDefinition() == typeof(IFacilityExtension<>))
.GenericTypeArguments[0];

Type extensionWrapperType = typeof(FacilityExtensionWrapper<>).MakeGenericType(contractType);
object extension = Activator.CreateInstance(extensionType)!;

return (IFacilityExtension<IFacility>)System.Activator.CreateInstance(extensionWrapperType, extension)!;
}

/// <summary>
/// Adds an extension to the facility.
/// </summary>
/// <remarks>
/// The type <paramref name="extensionType"/> must implement <see cref="IFacilityExtension{T}"/> with the
/// type of the facility.
/// The type <paramref name="extensionType"/> must implement <see cref="IFacilityExtension"/>.
/// </remarks>
/// <param name="extensionType">The type of the extension.</param>
/// <returns>The <see cref="FacilityBuilder"/> to allow chaining.</returns>
/// <exception cref="ArgumentNullException">Argument <paramref name="extensionType"/> is null.</exception>
/// <exception cref="ArgumentException">Argument <paramref name="extensionType"/> does not implement <see cref="IFacilityExtension{T}"/> with the type of the facility.</exception>
public FacilityBuilder AddExtension(Type extensionType)
/// <exception cref="ArgumentException">Argument <paramref name="extensionType"/> does not implement <see cref="IFacilityExtension"/> with the type of the facility.</exception>
public FacilityBuilder AddExtension(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type extensionType)
{
Ensure.Arg.NotNull(extensionType);
Ensure.Arg.OfType(extensionType, typeof(IFacilityExtension<>).MakeGenericType(FacilityType));
Ensure.Arg.OfType<IFacilityExtension>(extensionType);

IFacilityExtension<IFacility> extension = CreateExtension(extensionType);
var extension = (IFacilityExtension)Activator.CreateInstance(extensionType)!;
extension.ConfigureServices(Services);
return this;
}
Expand All @@ -82,7 +70,7 @@ public FacilityBuilder AddExtensionsFrom(Action<IFacilityExtensionReflectionBuil
var reflectionBuilder = new FacilityExtensionReflectionBuilder(Activator);
configure(reflectionBuilder);

foreach (IFacilityExtension<IFacility> extension in reflectionBuilder.Resolve(FacilityType))
foreach (IFacilityExtension extension in reflectionBuilder.Resolve(FacilityType))
{
extension.ConfigureServices(Services);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright (c) The AppCore .NET project.

using System;
using System.Linq;
using System.Diagnostics.CodeAnalysis;
using AppCoreNet.Diagnostics;
using AppCoreNet.Extensions.DependencyInjection.Activator;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -13,12 +13,23 @@ namespace AppCoreNet.Extensions.DependencyInjection.Facilities;
/// Provides a builder for facilities.
/// </summary>
/// <typeparam name="T">The type of the facility.</typeparam>
public sealed class FacilityBuilder<T> : FacilityBuilder
public sealed class FacilityBuilder<T>
where T : IFacility
{
/// <summary>
/// Gets the <see cref="IServiceCollection"/>.
/// </summary>
public IServiceCollection Services { get; }

/// <summary>
/// Gets the <see cref="IActivator"/>.
/// </summary>
public IActivator Activator { get; }

internal FacilityBuilder(IServiceCollection services, IActivator activator)
: base(services, activator, typeof(T))
{
Services = services;
Activator = activator;
}

/// <summary>
Expand All @@ -32,9 +43,13 @@ internal FacilityBuilder(IServiceCollection services, IActivator activator)
/// <returns>The <see cref="FacilityBuilder{T}"/> to allow chaining.</returns>
/// <exception cref="ArgumentNullException">Argument <paramref name="extensionType"/> is null.</exception>
/// <exception cref="ArgumentException">Argument <paramref name="extensionType"/> does not implement <see cref="IFacilityExtension{T}"/> with the type of the facility.</exception>
public new FacilityBuilder<T> AddExtension(Type extensionType)
public FacilityBuilder<T> AddExtension(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type extensionType)
{
base.AddExtension(extensionType);
Ensure.Arg.OfType<IFacilityExtension<T>>(extensionType);

var extension = (IFacilityExtension<T>)Activator.CreateInstance(extensionType)!;
extension.ConfigureServices(Services);
return this;
}

Expand All @@ -43,7 +58,8 @@ internal FacilityBuilder(IServiceCollection services, IActivator activator)
/// </summary>
/// <typeparam name="TExtension">The type of the extension.</typeparam>
/// <returns>The <see cref="FacilityBuilder{T}"/> to allow chaining.</returns>
public FacilityBuilder<T> AddExtension<TExtension>()
public FacilityBuilder<T> AddExtension<
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TExtension>()
where TExtension : class, IFacilityExtension<T>
{
IFacilityExtension<T> extension = Activator.CreateInstance<TExtension>()!;
Expand All @@ -65,14 +81,24 @@ public FacilityBuilder<T> AddExtension(IFacilityExtension<T> extension)
}

/// <summary>
/// Adds facility extensions using a <see cref="IFacilityExtensionReflectionBuilder"/> to the <see cref="IServiceCollection"/>.
/// Adds facility extensions using a <see cref="IFacilityExtensionReflectionBuilder"/> to the
/// <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="configure">The delegate used to configure the facility extension resolvers.</param>
/// <returns>The <see cref="FacilityBuilder{T}"/>.</returns>
/// <exception cref="ArgumentNullException">Argument <paramref name="configure"/> is null.</exception>
public new FacilityBuilder<T> AddExtensionsFrom(Action<IFacilityExtensionReflectionBuilder> configure)
public FacilityBuilder<T> AddExtensionsFrom(Action<IFacilityExtensionReflectionBuilder> configure)
{
base.AddExtensionsFrom(configure);
Ensure.Arg.NotNull(configure);

var reflectionBuilder = new FacilityExtensionReflectionBuilder(Activator);
configure(reflectionBuilder);

foreach (IFacilityExtension extension in reflectionBuilder.Resolve(typeof(T)))
{
extension.ConfigureServices(Services);
}

return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using AppCoreNet.Diagnostics;
using AppCoreNet.Extensions.DependencyInjection.Activator;
Expand All @@ -26,21 +27,18 @@ public IFacilityExtensionReflectionBuilder AddResolver(IFacilityExtensionResolve
return this;
}

public IFacilityExtensionReflectionBuilder AddResolver<T>(Action<T>? configure = null)
public IFacilityExtensionReflectionBuilder AddResolver<
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(Action<T>? configure = null)
where T : IFacilityExtensionResolver
{
var resolver = _activator.CreateInstance<T>()!;
configure?.Invoke(resolver);
return AddResolver(resolver);
}

public IReadOnlyCollection<IFacilityExtension<IFacility>> Resolve(Type facilityType)
public IReadOnlyCollection<IFacilityExtension> Resolve(Type facilityType)
{
Type[] facilityTypes = facilityType.GetTypesAssignableFrom()
.Where(t => t.GetInterfaces().Contains(typeof(IFacility)))
.ToArray();

return _resolvers.SelectMany(s => facilityTypes.SelectMany(s.Resolve))
return _resolvers.SelectMany(s => s.Resolve(facilityType))
.ToList()
.AsReadOnly();
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using AppCoreNet.Diagnostics;
using AppCoreNet.Extensions.DependencyInjection.Activator;
Expand All @@ -28,7 +29,8 @@ public IFacilityReflectionBuilder AddResolver(IFacilityResolver resolver)
return this;
}

public IFacilityReflectionBuilder AddResolver<T>(Action<T>? configure = null)
public IFacilityReflectionBuilder AddResolver<
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(Action<T>? configure = null)
where T : IFacilityResolver
{
var resolver = _activator.CreateInstance<T>()!;
Expand All @@ -43,7 +45,7 @@ public IFacilityReflectionBuilder AddExtensionsFrom(Action<IFacilityExtensionRef
return this;
}

public IReadOnlyCollection<(IFacility Facility, IReadOnlyCollection<IFacilityExtension<IFacility>>
public IReadOnlyCollection<(IFacility Facility, IReadOnlyCollection<IFacilityExtension>
FacilityExtensions)> Resolve()
{
List<IFacility> facilities =
Expand All @@ -58,15 +60,15 @@ public IFacilityReflectionBuilder AddExtensionsFrom(Action<IFacilityExtensionRef
_extensionsConfig(extensionReflectionBuilder);
}

ReadOnlyCollection<IFacilityExtension<IFacility>> emptyFacilityExtensions =
new List<IFacilityExtension<IFacility>>().AsReadOnly();
ReadOnlyCollection<IFacilityExtension> emptyFacilityExtensions =
new List<IFacilityExtension>().AsReadOnly();

List<(IFacility Facility, IReadOnlyCollection<IFacilityExtension<IFacility>> FacilityExtensions)> result =
List<(IFacility Facility, IReadOnlyCollection<IFacilityExtension> FacilityExtensions)> result =
new();

foreach (IFacility facility in facilities)
{
IReadOnlyCollection<IFacilityExtension<IFacility>> facilityExtensions =
IReadOnlyCollection<IFacilityExtension> facilityExtensions =
extensionReflectionBuilder?.Resolve(facility.GetType())
?? emptyFacilityExtensions;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ namespace AppCoreNet.Extensions.DependencyInjection.Facilities;
/// <summary>
/// Represents an extension for a facility.
/// </summary>
/// <typeparam name="T">The type of the facility.</typeparam>
public interface IFacilityExtension<in T>
where T : IFacility
public interface IFacilityExtension
{
/// <summary>
/// Must be implemented to register services with the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
void ConfigureServices(IServiceCollection services);
}

/// <summary>
/// Represents an extension for a facility.
/// </summary>
/// <typeparam name="T">The type of the facility.</typeparam>
public interface IFacilityExtension<in T> : IFacilityExtension
where T : IFacility
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;

namespace AppCoreNet.Extensions.DependencyInjection.Facilities;

Expand All @@ -27,6 +28,7 @@ public interface IFacilityExtensionReflectionBuilder
/// <param name="configure">The configuration delegate.</param>
/// <returns>The <see cref="IFacilityExtensionReflectionBuilder"/> to allow chaining.</returns>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public IFacilityExtensionReflectionBuilder AddResolver<T>(Action<T>? configure = null)
public IFacilityExtensionReflectionBuilder AddResolver<
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(Action<T>? configure = null)
where T : IFacilityExtensionResolver;
}
Loading
Loading