diff --git a/src/Bindicate/Bindicate.csproj b/src/Bindicate/Bindicate.csproj
index 1463f87..933c4f3 100644
--- a/src/Bindicate/Bindicate.csproj
+++ b/src/Bindicate/Bindicate.csproj
@@ -13,7 +13,7 @@
di, ioc, service, collection, extensions, attribute
Add support for IOptions
LICENSE.txt
- 1.5
+ 1.5.1
diff --git a/src/Bindicate/Configuration/AutowiringBuilder.cs b/src/Bindicate/Configuration/AutowiringBuilder.cs
index 02db74e..bf5cf7a 100644
--- a/src/Bindicate/Configuration/AutowiringBuilder.cs
+++ b/src/Bindicate/Configuration/AutowiringBuilder.cs
@@ -3,6 +3,7 @@
using Bindicate.Attributes.Scoped;
using Bindicate.Attributes.Singleton;
using Bindicate.Attributes.Transient;
+using Bindicate.Configuration;
using Bindicate.Lifetime;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -14,16 +15,32 @@ namespace Bindicate;
public class AutowiringBuilder
{
private IServiceCollection _services { get; }
+ private readonly List _typeMetadatas;
- private Assembly _targetAssembly { get; }
public AutowiringBuilder(IServiceCollection services, Assembly targetAssembly)
{
_services = services;
- _targetAssembly = targetAssembly;
+ _typeMetadatas = ScanAssembly(targetAssembly);
AddAutowiringForAssembly();
}
+ private List ScanAssembly(Assembly assembly)
+ {
+ var typeMetadatas = new List();
+
+ foreach (var type in assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract))
+ {
+ var hasRegisterOptionsAttribute = type.GetCustomAttributes(typeof(RegisterOptionsAttribute), false).Any();
+ var hasBaseServiceAttribute = type.GetCustomAttributes(typeof(BaseServiceAttribute), false).Any();
+ var hasBaseKeyedServiceAttribute = type.GetCustomAttributes(typeof(BaseKeyedServiceAttribute), false).Any();
+
+ var typeMetadata = new TypeMetadata(type, hasRegisterOptionsAttribute, hasBaseServiceAttribute, hasBaseKeyedServiceAttribute);
+ typeMetadatas.Add(typeMetadata);
+ }
+
+ return typeMetadatas;
+ }
///
/// Scans the assembly to automatically wire up services based on the attributes.
@@ -31,46 +48,50 @@ public AutowiringBuilder(IServiceCollection services, Assembly targetAssembly)
/// A reference to this instance after the operation has completed.
public AutowiringBuilder AddAutowiringForAssembly()
{
- foreach (var type in _targetAssembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract))
+ foreach (var typeMetadata in _typeMetadatas)
{
- var registerAttributes = type.GetCustomAttributes(typeof(BaseServiceAttribute), false)
- .Cast();
-
- foreach (var attr in registerAttributes)
+ if (typeMetadata.HasBaseServiceAttribute)
{
- var serviceType = attr.ServiceType ?? type;
- var registrationMethod = GetRegistrationMethod(_services, attr.Lifetime);
+ var type = typeMetadata.Type;
+ var registerAttributes = type.GetCustomAttributes(typeof(BaseServiceAttribute), false)
+ .Cast();
- if (serviceType.IsDefined(typeof(RegisterGenericInterfaceAttribute), false))
+ foreach (var attr in registerAttributes)
{
- if (serviceType.IsGenericType)
- {
- _services.Add(ServiceDescriptor.Describe(
- serviceType.GetGenericTypeDefinition(),
- type.GetGenericTypeDefinition(),
- attr.Lifetime.ConvertToServiceLifetime())
- );
- }
- else
+ var serviceType = attr.ServiceType ?? type;
+ var registrationMethod = GetRegistrationMethod(_services, attr.Lifetime);
+
+ if (serviceType.IsDefined(typeof(RegisterGenericInterfaceAttribute), false))
{
- // Handle non-generic services with generic interfaces
- foreach (var iface in type.GetInterfaces())
+ if (serviceType.IsGenericType)
{
- if (iface.IsGenericType && iface.GetGenericTypeDefinition().IsDefined(typeof(RegisterGenericInterfaceAttribute), false))
+ _services.Add(ServiceDescriptor.Describe(
+ serviceType.GetGenericTypeDefinition(),
+ type.GetGenericTypeDefinition(),
+ attr.Lifetime.ConvertToServiceLifetime())
+ );
+ }
+ else
+ {
+ // Handle non-generic services with generic interfaces
+ foreach (var iface in type.GetInterfaces())
{
- var genericInterface = iface.GetGenericTypeDefinition();
- _services.Add(ServiceDescriptor.Describe(genericInterface, type, attr.Lifetime.ConvertToServiceLifetime()));
+ if (iface.IsGenericType && iface.GetGenericTypeDefinition().IsDefined(typeof(RegisterGenericInterfaceAttribute), false))
+ {
+ var genericInterface = iface.GetGenericTypeDefinition();
+ _services.Add(ServiceDescriptor.Describe(genericInterface, type, attr.Lifetime.ConvertToServiceLifetime()));
+ }
}
}
}
- }
- else if (type.GetInterfaces().Contains(serviceType) || type == serviceType)
- {
- RegisterService(serviceType, type, registrationMethod);
- }
- else
- {
- throw new InvalidOperationException($"Type {type.FullName} does not implement {serviceType.FullName}");
+ else if (type.GetInterfaces().Contains(serviceType) || type == serviceType)
+ {
+ RegisterService(serviceType, type, registrationMethod);
+ }
+ else
+ {
+ throw new InvalidOperationException($"Type {type.FullName} does not implement {serviceType.FullName}");
+ }
}
}
}
@@ -86,24 +107,28 @@ public AutowiringBuilder AddAutowiringForAssembly()
/// A reference to this instance after the operation has completed.
public AutowiringBuilder WithOptions(IConfiguration configuration)
{
- foreach (var type in _targetAssembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract))
+ foreach (var typeMetadata in _typeMetadatas)
{
- var optionAttributes = type.GetCustomAttributes(typeof(RegisterOptionsAttribute), false)
+ if (typeMetadata.HasRegisterOptionsAttribute)
+ {
+ var type = typeMetadata.Type;
+ var optionAttributes = type.GetCustomAttributes(typeof(RegisterOptionsAttribute), false)
.Cast();
- foreach (var attr in optionAttributes)
- {
- var configSection = configuration.GetSection(attr.ConfigurationSection);
+ foreach (var attr in optionAttributes)
+ {
+ var configSection = configuration.GetSection(attr.ConfigurationSection);
- if (!configSection.Exists())
- throw new InvalidOperationException($"Missing configuration section: {attr.ConfigurationSection}");
+ if (!configSection.Exists())
+ throw new InvalidOperationException($"Missing configuration section: {attr.ConfigurationSection}");
- var genericOptionsConfigureMethod = typeof(OptionsConfigurationServiceCollectionExtensions)
- .GetMethods()
- .FirstOrDefault(m => m.Name == "Configure" && m.GetParameters().Length == 2);
+ var genericOptionsConfigureMethod = typeof(OptionsConfigurationServiceCollectionExtensions)
+ .GetMethods()
+ .FirstOrDefault(m => m.Name == "Configure" && m.GetParameters().Length == 2);
- var specializedMethod = genericOptionsConfigureMethod.MakeGenericMethod(type);
- specializedMethod.Invoke(null, new object[] { _services, configSection });
+ var specializedMethod = genericOptionsConfigureMethod.MakeGenericMethod(type);
+ specializedMethod.Invoke(null, new object[] { _services, configSection });
+ }
}
}
@@ -116,19 +141,24 @@ public AutowiringBuilder WithOptions(IConfiguration configuration)
/// A reference to this instance after the operation has completed.
public AutowiringBuilder ForKeyedServices()
{
- foreach (var type in _targetAssembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract))
+ foreach (var typeMetadata in _typeMetadatas)
{
- var keyedAttributes = type.GetCustomAttributes(typeof(BaseKeyedServiceAttribute), false)
+ if (typeMetadata.HasBaseKeyedServiceAttribute)
+ {
+ var type = typeMetadata.Type;
+
+ var keyedAttributes = type.GetCustomAttributes(typeof(BaseKeyedServiceAttribute), false)
.Cast();
- foreach (var attr in keyedAttributes)
- {
- var serviceType = attr.ServiceType ?? type;
- var key = attr.Key;
+ foreach (var attr in keyedAttributes)
+ {
+ var serviceType = attr.ServiceType ?? type;
+ var key = attr.Key;
- var registrationMethod = GetKeyedRegistrationMethod(_services, attr);
+ var registrationMethod = GetKeyedRegistrationMethod(_services, attr);
- registrationMethod(serviceType, key, type);
+ registrationMethod(serviceType, key, type);
+ }
}
}
diff --git a/src/Bindicate/Configuration/TypeMetadata.cs b/src/Bindicate/Configuration/TypeMetadata.cs
new file mode 100644
index 0000000..48d5e81
--- /dev/null
+++ b/src/Bindicate/Configuration/TypeMetadata.cs
@@ -0,0 +1,17 @@
+namespace Bindicate.Configuration;
+
+public class TypeMetadata
+{
+ public Type Type { get; }
+ public bool HasRegisterOptionsAttribute { get; }
+ public bool HasBaseServiceAttribute { get; }
+ public bool HasBaseKeyedServiceAttribute { get; }
+
+ public TypeMetadata(Type type, bool hasRegisterOptionsAttribute, bool hasBaseServiceAttribute, bool hasBaseKeyedServiceAttribute)
+ {
+ Type = type;
+ HasRegisterOptionsAttribute = hasRegisterOptionsAttribute;
+ HasBaseServiceAttribute = hasBaseServiceAttribute;
+ HasBaseKeyedServiceAttribute = hasBaseKeyedServiceAttribute;
+ }
+}
\ No newline at end of file