-
-
Notifications
You must be signed in to change notification settings - Fork 238
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allowing more decoration methods to support open generic types.
- Loading branch information
1 parent
df48b72
commit ffef7cd
Showing
3 changed files
with
103 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,26 @@ | ||
using System; | ||
|
||
namespace Scrutor.Decoration | ||
{ | ||
internal static class DecorationFactory | ||
{ | ||
public static Decoration Create(Type serviceType, Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory) | ||
{ | ||
IDecorationStrategy strategy; | ||
|
||
if (serviceType.IsOpenGeneric() && decoratorType is not null && decoratorType.IsOpenGeneric()) | ||
{ | ||
strategy = new OpenGenericDecorationStrategy(serviceType, decoratorType); | ||
} | ||
else | ||
{ | ||
strategy = new ClosedTypeDecorationStrategy(serviceType, decoratorType, decoratorFactory); | ||
} | ||
|
||
return new Decoration(strategy); | ||
} | ||
|
||
public static Decoration Create<TService>(Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory) | ||
=> new(new ClosedTypeDecorationStrategy(typeof(TService), decoratorType, decoratorFactory)); | ||
} | ||
} | ||
using System; | ||
|
||
namespace Scrutor.Decoration | ||
{ | ||
internal static class DecorationFactory | ||
{ | ||
public static Decoration Create(Type serviceType, Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory) | ||
{ | ||
IDecorationStrategy strategy; | ||
|
||
if (serviceType.IsOpenGeneric()) | ||
{ | ||
strategy = new OpenGenericDecorationStrategy(serviceType, decoratorType, decoratorFactory); | ||
} | ||
else | ||
{ | ||
strategy = new ClosedTypeDecorationStrategy(serviceType, decoratorType, decoratorFactory); | ||
} | ||
|
||
return new Decoration(strategy); | ||
} | ||
|
||
public static Decoration Create<TService>(Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory) | ||
=> new(new ClosedTypeDecorationStrategy(typeof(TService), decoratorType, decoratorFactory)); | ||
} | ||
} |
136 changes: 74 additions & 62 deletions
136
src/Scrutor/Decoration/OpenGenericDecorationStrategy.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,74 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System; | ||
|
||
namespace Scrutor.Decoration | ||
{ | ||
internal class OpenGenericDecorationStrategy : IDecorationStrategy | ||
{ | ||
private readonly Type _serviceType; | ||
private readonly Type _decoratorType; | ||
|
||
public OpenGenericDecorationStrategy(Type serviceType, Type decoratorType) | ||
{ | ||
_serviceType = serviceType; | ||
_decoratorType = decoratorType; | ||
} | ||
|
||
public Type ServiceType => _serviceType; | ||
|
||
public bool CanDecorate(Type serviceType) | ||
{ | ||
var canHandle = serviceType.IsGenericType | ||
&& (!serviceType.IsGenericTypeDefinition) | ||
&& _serviceType.GetGenericTypeDefinition() == serviceType.GetGenericTypeDefinition() | ||
&& HasCompatibleGenericArguments(serviceType); | ||
|
||
return canHandle; | ||
} | ||
|
||
public Func<IServiceProvider, object> CreateDecorator(ServiceDescriptor descriptor) | ||
{ | ||
var genericArguments = descriptor.ServiceType.GetGenericArguments(); | ||
var closedDecorator = _decoratorType.MakeGenericType(genericArguments); | ||
|
||
return DecoratorInstanceFactory.Default(descriptor, closedDecorator); | ||
} | ||
|
||
private bool HasCompatibleGenericArguments(Type serviceType) | ||
{ | ||
var canHandle = false; | ||
|
||
if (_decoratorType is null) | ||
{ | ||
canHandle = true; | ||
} | ||
else | ||
{ | ||
var genericArguments = serviceType.GetGenericArguments(); | ||
|
||
try | ||
{ | ||
_ = _decoratorType.MakeGenericType(genericArguments); | ||
canHandle = true; | ||
} | ||
catch (ArgumentException) | ||
{ | ||
} | ||
} | ||
|
||
return canHandle; | ||
} | ||
} | ||
} | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System; | ||
|
||
namespace Scrutor.Decoration | ||
{ | ||
internal sealed class OpenGenericDecorationStrategy : IDecorationStrategy | ||
{ | ||
private readonly Type _serviceType; | ||
private readonly Type? _decoratorType; | ||
private readonly Func<object, IServiceProvider, object>? _decoratorFactory; | ||
|
||
public OpenGenericDecorationStrategy(Type serviceType, Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory) | ||
{ | ||
_serviceType = serviceType; | ||
_decoratorType = decoratorType; | ||
_decoratorFactory = decoratorFactory; | ||
} | ||
|
||
public Type ServiceType => _serviceType; | ||
|
||
public bool CanDecorate(Type serviceType) | ||
{ | ||
var canHandle = serviceType.IsGenericType | ||
&& (!serviceType.IsGenericTypeDefinition) | ||
&& _serviceType.GetGenericTypeDefinition() == serviceType.GetGenericTypeDefinition() | ||
&& HasCompatibleGenericArguments(serviceType); | ||
|
||
return canHandle; | ||
} | ||
|
||
public Func<IServiceProvider, object> CreateDecorator(ServiceDescriptor descriptor) | ||
{ | ||
if (_decoratorType is not null) | ||
{ | ||
var genericArguments = descriptor.ServiceType.GetGenericArguments(); | ||
var closedDecorator = _decoratorType.MakeGenericType(genericArguments); | ||
|
||
return DecoratorInstanceFactory.Default(descriptor, closedDecorator); | ||
} | ||
|
||
if (_decoratorFactory is not null) | ||
{ | ||
return DecoratorInstanceFactory.Custom(descriptor, _decoratorFactory); | ||
} | ||
|
||
throw new InvalidOperationException($"Both serviceType and decoratorFactory can not be null."); | ||
} | ||
|
||
private bool HasCompatibleGenericArguments(Type serviceType) | ||
{ | ||
var canHandle = false; | ||
|
||
if (_decoratorType is null) | ||
{ | ||
canHandle = true; | ||
} | ||
else | ||
{ | ||
var genericArguments = serviceType.GetGenericArguments(); | ||
|
||
try | ||
{ | ||
_ = _decoratorType.MakeGenericType(genericArguments); | ||
canHandle = true; | ||
} | ||
catch (ArgumentException) | ||
{ | ||
} | ||
} | ||
|
||
return canHandle; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters