Skip to content

Commit

Permalink
Merge pull request #6 from Tim-Maes/feature/add-summaries
Browse files Browse the repository at this point in the history
Add summaries
  • Loading branch information
Tim-Maes authored Oct 11, 2023
2 parents 53baa6b + ff814f9 commit 8e1928b
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 36 deletions.
4 changes: 4 additions & 0 deletions src/Bindicate/Attributes/Scoped/AddScopedAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
namespace Bindicate.Attributes;

/// <summary>
/// Specifies that a service should be registered with the dependency injection container with a scoped lifetime.
/// This means a new instance is created once per scope.
/// </summary>
public class AddScopedAttribute : BaseServiceAttribute
{
public override Lifetime Lifetime => Lifetime.Scoped;
Expand Down
5 changes: 5 additions & 0 deletions src/Bindicate/Attributes/Scoped/TryAddScopedAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
namespace Bindicate.Attributes;

/// <summary>
/// Specifies that a service should be registered with the dependency injection container for the lifetime of a scope.
/// Unlike the <see cref="AddScopedAttribute"/>, if the service is already registered with the container,
/// this attribute doesn't replace the existing registration.
/// </summary>
public class TryAddScopedAttribute : BaseServiceAttribute
{
public override Lifetime Lifetime => Lifetime.TryAddScoped;
Expand Down
4 changes: 4 additions & 0 deletions src/Bindicate/Attributes/Singleton/AddSingletonAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
namespace Bindicate.Attributes;

/// <summary>
/// Specifies that a service should be registered with the dependency injection container with a singleton lifetime.
/// This means a single instance is created and it acts as a singleton.
/// </summary>
public class AddSingletonAttribute : BaseServiceAttribute
{
public override Lifetime Lifetime => Lifetime.Singleton;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
namespace Bindicate.Attributes;

/// <summary>
/// Attempts to register a service with the dependency injection container with a singleton lifetime.
/// If a service with the same type is already registered, the existing registration is preserved.
/// </summary>
public class TryAddSingletonAttribute : BaseServiceAttribute
{
public override Lifetime Lifetime => Lifetime.TryAddSingleton;
Expand Down
4 changes: 4 additions & 0 deletions src/Bindicate/Attributes/Transient/AddTransientAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
namespace Bindicate.Attributes;

/// <summary>
/// Specifies that a service should be registered with the dependency injection container with a transient lifetime.
/// This means a new instance is created every time it is requested.
/// </summary>
public class AddTransientAttribute : BaseServiceAttribute
{
public override Lifetime Lifetime => Lifetime.Transient;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
namespace Bindicate.Attributes;

/// <summary>
/// Attempts to register a service with the dependency injection container with a transient lifetime.
/// If a service with the same type is already registered, the existing registration is preserved.
/// </summary>
public class TryAddTransientAttribute : BaseServiceAttribute
{
public override Lifetime Lifetime => Lifetime.TryAddTransient;
Expand Down
2 changes: 1 addition & 1 deletion src/Bindicate/Bindicate.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageTags>di, ioc, service, collection, extensions, attribute</PackageTags>
<PackageReleaseNotes>Add TryAddScoped, TryAddTransient and TryAddSingleton</PackageReleaseNotes>
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<Version>1.1.5</Version>
<Version>1.1.6</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
76 changes: 41 additions & 35 deletions src/Bindicate/Configuration/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,62 @@ namespace Bindicate.Configuration;

public static class ServiceCollectionExtensions
{
/// <summary>
/// Registers services decorated with <see cref="BaseServiceAttribute"/> derivatives in the specified assembly.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
/// <param name="assembly">The assembly to scan for types decorated with service registration attributes.</param>
/// <returns>The same service collection so that multiple calls can be chained.</returns>
/// <exception cref="InvalidOperationException">Thrown when a type does not implement the specified service interface.</exception>
public static IServiceCollection AddBindicate(this IServiceCollection services, Assembly assembly)
{
foreach (var type in assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract))
var types = assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract);

foreach (var type in types)
{
var registerAttributes = type.GetCustomAttributes(typeof(BaseServiceAttribute), false)
.Cast<BaseServiceAttribute>();

foreach (var attr in registerAttributes)
{
var serviceType = attr.ServiceType ?? type;

if (type.GetInterfaces().Contains(serviceType) || type == serviceType)
{
switch (attr.Lifetime)
{
case Lifetime.Scoped:
RegisterService(serviceType, type, (s, t) => services.AddScoped(s, t));
break;
case Lifetime.TryAddScoped:
RegisterService(serviceType, type, (s, t) => services.TryAddScoped(s, t));
break;
case Lifetime.Singleton:
RegisterService(serviceType, type, (s, t) => services.AddSingleton(s, t));
break;
case Lifetime.TryAddSingleton:
RegisterService(serviceType, type, (s, t) => services.TryAddSingleton(s, t));
break;
case Lifetime.Transient:
RegisterService(serviceType, type, (s, t) => services.AddTransient(s, t));
break;
case Lifetime.TryAddTransient:
RegisterService(serviceType, type, (s, t) => services.TryAddTransient(s, t));
break;
}
}
else
{
throw new InvalidOperationException($"Type {type.FullName} does not implement {serviceType.FullName}");
}
RegisterServiceBasedOnLifetime(services, type, attr);
}
}

return services;
}

private static void RegisterService(Type serviceType, Type implementationType, Action<Type, Type?> registrationMethod)
private static void RegisterServiceBasedOnLifetime(IServiceCollection services, Type type, BaseServiceAttribute attr)
{
if (serviceType == implementationType)
registrationMethod(implementationType, implementationType);
var serviceType = attr.ServiceType ?? type;

if (type.GetInterfaces().Contains(serviceType) || type == serviceType)
{
switch (attr.Lifetime)
{
case Lifetime.Scoped:
services.AddScoped(serviceType, type);
break;
case Lifetime.TryAddScoped:
services.TryAddScoped(serviceType, type);
break;
case Lifetime.Singleton:
services.AddSingleton(serviceType, type);
break;
case Lifetime.TryAddSingleton:
services.TryAddSingleton(serviceType, type);
break;
case Lifetime.Transient:
services.AddTransient(serviceType, type);
break;
case Lifetime.TryAddTransient:
services.TryAddTransient(serviceType, type);
break;
}
}
else
registrationMethod(serviceType, implementationType);
{
throw new InvalidOperationException($"Type {type.FullName} does not implement {serviceType.FullName}");
}
}
}

0 comments on commit 8e1928b

Please sign in to comment.