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
8 changes: 7 additions & 1 deletion src/Injectio.Attributes/RegistrationStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@ public enum RegistrationStrategy
/// <summary>
/// Registers each matching concrete type as all of its implemented interfaces and itself
/// </summary>
SelfWithInterfaces = 2
SelfWithInterfaces = 2,
/// <summary>
/// Registers each matching concrete type as all of its implemented interfaces and itself.
/// For the interfaces a proxy-factory resolves the service from its type-name, so only one instance is created per lifetime
/// </summary>
/// <remarks>For open-generic registrations, this behaves like <see cref="SelfWithInterfaces"/></remarks>
SelfWithProxyFactory = 3
}
16 changes: 10 additions & 6 deletions src/Injectio.Generators/KnownTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,33 @@ public static class KnownTypes
public const string ServiceLifetimeTransientFullName = "Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient";


public static readonly int DuplicateStrategySkipValue = 0;
public const int DuplicateStrategySkipValue = 0;
public const string DuplicateStrategySkipShortName = "Skip";
public const string DuplicateStrategySkipTypeName = $"DuplicateStrategy.{DuplicateStrategySkipShortName}";

public static readonly int DuplicateStrategyReplaceValue = 1;
public const int DuplicateStrategyReplaceValue = 1;
public const string DuplicateStrategyReplaceShortName = "Replace";
public const string DuplicateStrategyReplaceTypeName = $"DuplicateStrategy.{DuplicateStrategyReplaceShortName}";

public static readonly int DuplicateStrategyAppendValue = 2;
public const int DuplicateStrategyAppendValue = 2;
public const string DuplicateStrategyAppendShortName = "Append";
public const string DuplicateStrategyAppendTypeName = $"DuplicateStrategy.{DuplicateStrategyAppendShortName}";


public static readonly int RegistrationStrategySelfValue = 0;
public const int RegistrationStrategySelfValue = 0;
public const string RegistrationStrategySelfShortName = "Self";
public const string RegistrationStrategySelfTypeName = $"RegistrationStrategy.{RegistrationStrategySelfShortName}";

public static readonly int RegistrationStrategyImplementedInterfacesValue = 1;
public const int RegistrationStrategyImplementedInterfacesValue = 1;
public const string RegistrationStrategyImplementedInterfacesShortName = "ImplementedInterfaces";
public const string RegistrationStrategyImplementedInterfacesTypeName = $"RegistrationStrategy.{RegistrationStrategyImplementedInterfacesShortName}";

public static readonly int RegistrationStrategySelfWithInterfacesValue = 2;
public const int RegistrationStrategySelfWithInterfacesValue = 2;
public const string RegistrationStrategySelfWithInterfacesShortName = "SelfWithInterfaces";
public const string RegistrationStrategySelfWithInterfacesTypeName = $"RegistrationStrategy.{RegistrationStrategySelfWithInterfacesShortName}";

public const int RegistrationStrategySelfWithProxyFactoryValue = 3;
public const string RegistrationStrategySelfWithProxyFactoryShortName = "SelfWithProxyFactory";
public const string RegistrationStrategySelfWithProxyFactoryTypeName = $"RegistrationStrategy.{RegistrationStrategySelfWithProxyFactoryShortName}";

}
33 changes: 22 additions & 11 deletions src/Injectio.Generators/ServiceRegistrationGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ private static (EquatableArray<Diagnostic> diagnostics, bool hasServiceCollectio
&& implementationType == null
&& serviceTypes.Count == 0)
{
registrationStrategy = KnownTypes.RegistrationStrategySelfWithInterfacesShortName;
registrationStrategy = KnownTypes.RegistrationStrategySelfWithProxyFactoryShortName;
}

// no implementation type set, use class attribute is on
Expand All @@ -348,7 +348,9 @@ private static (EquatableArray<Diagnostic> diagnostics, bool hasServiceCollectio
}

// add implemented interfaces
bool includeInterfaces = registrationStrategy is KnownTypes.RegistrationStrategyImplementedInterfacesShortName or KnownTypes.RegistrationStrategySelfWithInterfacesShortName;
bool includeInterfaces = registrationStrategy is KnownTypes.RegistrationStrategyImplementedInterfacesShortName
or KnownTypes.RegistrationStrategySelfWithInterfacesShortName
or KnownTypes.RegistrationStrategySelfWithProxyFactoryShortName;
if (includeInterfaces)
{
foreach (var implementedInterface in classSymbol.AllInterfaces)
Expand All @@ -366,10 +368,18 @@ private static (EquatableArray<Diagnostic> diagnostics, bool hasServiceCollectio
}

// add class attribute is on; default service type if not set
bool includeSelf = registrationStrategy is KnownTypes.RegistrationStrategySelfShortName or KnownTypes.RegistrationStrategySelfWithInterfacesShortName;
bool includeSelf = registrationStrategy is KnownTypes.RegistrationStrategySelfShortName
or KnownTypes.RegistrationStrategySelfWithInterfacesShortName
or KnownTypes.RegistrationStrategySelfWithProxyFactoryShortName;
if (includeSelf || serviceTypes.Count == 0)
serviceTypes.Add(implementationType!);

if (registrationStrategy is null && serviceTypes.Contains(implementationType!))
registrationStrategy = KnownTypes.RegistrationStrategySelfWithProxyFactoryShortName;

if (registrationStrategy is KnownTypes.RegistrationStrategySelfWithProxyFactoryShortName && isOpenGeneric)
registrationStrategy = KnownTypes.RegistrationStrategySelfWithInterfacesShortName;

return new ServiceRegistration(
Lifetime: serviceLifetime,
ImplementationType: implementationType!,
Expand Down Expand Up @@ -529,9 +539,9 @@ private static string ResolveDuplicateStrategy(object? value)
{
int v => v switch
{
0 => KnownTypes.DuplicateStrategySkipShortName,
1 => KnownTypes.DuplicateStrategyReplaceShortName,
2 => KnownTypes.DuplicateStrategyAppendShortName,
KnownTypes.DuplicateStrategySkipValue => KnownTypes.DuplicateStrategySkipShortName,
KnownTypes.DuplicateStrategyReplaceValue => KnownTypes.DuplicateStrategyReplaceShortName,
KnownTypes.DuplicateStrategyAppendValue => KnownTypes.DuplicateStrategyAppendShortName,
_ => KnownTypes.DuplicateStrategySkipShortName
},
string text => text,
Expand All @@ -545,13 +555,14 @@ private static string ResolveRegistrationStrategy(object? value)
{
int v => v switch
{
0 => KnownTypes.RegistrationStrategySelfShortName,
1 => KnownTypes.RegistrationStrategyImplementedInterfacesShortName,
2 => KnownTypes.RegistrationStrategySelfWithInterfacesShortName,
_ => KnownTypes.RegistrationStrategySelfWithInterfacesShortName
KnownTypes.RegistrationStrategySelfValue => KnownTypes.RegistrationStrategySelfShortName,
KnownTypes.RegistrationStrategyImplementedInterfacesValue => KnownTypes.RegistrationStrategyImplementedInterfacesShortName,
KnownTypes.RegistrationStrategySelfWithInterfacesValue => KnownTypes.RegistrationStrategySelfWithInterfacesShortName,
KnownTypes.RegistrationStrategySelfWithProxyFactoryValue => KnownTypes.RegistrationStrategySelfWithProxyFactoryShortName,
_ => KnownTypes.RegistrationStrategySelfWithProxyFactoryShortName
},
string text => text,
_ => KnownTypes.RegistrationStrategySelfWithInterfacesShortName
_ => KnownTypes.RegistrationStrategySelfWithProxyFactoryShortName
};
}
}
17 changes: 17 additions & 0 deletions src/Injectio.Generators/ServiceRegistrationWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,23 @@ private static void WriteServiceGeneric(
.AppendIf(".", !hasNamespace)
.Append(serviceRegistration.Factory);
}
else if (serviceRegistration.Registration == KnownTypes.RegistrationStrategySelfWithProxyFactoryShortName
&& serviceRegistration.ImplementationType != serviceType)
{
codeBuilder
.AppendIf(", ", serviceRegistration.ServiceKey.HasValue())
.Append("(serviceProvider")
.AppendIf(", key", serviceRegistration.ServiceKey.HasValue())
.Append(") => global::Microsoft.Extensions.DependencyInjection.ServiceProvider")
.Append(serviceRegistration.ServiceKey.HasValue()
? "KeyedServiceExtensions.GetRequiredKeyedService<"
: "ServiceExtensions.GetRequiredService<")
.AppendIf("global::", !serviceRegistration.ImplementationType.StartsWith("global::"))
.Append(serviceRegistration.ImplementationType)
.Append(">(serviceProvider")
.AppendIf(", key", serviceRegistration.ServiceKey.HasValue())
.Append(")");
}

codeBuilder
.AppendLine(")")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Microsoft.Extensions.DependencyInjection

global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAdd(
serviceCollection,
global::Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Scoped<global::Injectio.Sample.IService, global::Injectio.Sample.SingletonService>()
global::Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Scoped<global::Injectio.Sample.IService, global::Injectio.Sample.SingletonService>((serviceProvider) => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<global::Injectio.Sample.SingletonService>(serviceProvider))
);

global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAdd(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Microsoft.Extensions.DependencyInjection

global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAdd(
serviceCollection,
global::Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton<global::Injectio.Sample.IClosedGeneric<object>, global::Injectio.Sample.Service>()
global::Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton<global::Injectio.Sample.IClosedGeneric<object>, global::Injectio.Sample.Service>((serviceProvider) => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<global::Injectio.Sample.Service>(serviceProvider))
);

global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAdd(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace Microsoft.Extensions.DependencyInjection
{
global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAdd(
serviceCollection,
global::Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton<global::Injectio.Sample.IServiceTag, global::Injectio.Sample.ServiceTag>()
global::Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Singleton<global::Injectio.Sample.IServiceTag, global::Injectio.Sample.ServiceTag>((serviceProvider) => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<global::Injectio.Sample.ServiceTag>(serviceProvider))
);

global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAdd(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Microsoft.Extensions.DependencyInjection

global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAdd(
serviceCollection,
global::Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Transient<global::Injectio.Sample.IService, global::Injectio.Sample.SingletonService>()
global::Microsoft.Extensions.DependencyInjection.ServiceDescriptor.Transient<global::Injectio.Sample.IService, global::Injectio.Sample.SingletonService>((serviceProvider) => global::Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<global::Injectio.Sample.SingletonService>(serviceProvider))
);

global::Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions.TryAdd(
Expand Down