| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | using System; |
| | | 5 | | using CoreWCF.Channels; |
| | | 6 | | using Microsoft.Extensions.DependencyInjection; |
| | | 7 | | |
| | | 8 | | namespace CoreWCF.Dispatcher |
| | | 9 | | { |
| | | 10 | | internal class DependencyInjectionWithLegacyFallbackInstanceProvider : IInstanceProvider |
| | | 11 | | { |
| | | 12 | | private class ScopedServiceProviderExtension : IExtension<InstanceContext>, IKeyedServiceProvider, IDisposable |
| | | 13 | | { |
| | | 14 | | private readonly IServiceScope _serviceScope; |
| | 4 | 15 | | private IKeyedServiceProvider KeyedServiceProvider { get; } |
| | | 16 | | |
| | 1906 | 17 | | public ScopedServiceProviderExtension(IServiceProvider serviceProvider) |
| | | 18 | | { |
| | 1906 | 19 | | _serviceScope = serviceProvider.CreateScope(); |
| | 1906 | 20 | | KeyedServiceProvider = _serviceScope.ServiceProvider as IKeyedServiceProvider; |
| | 1906 | 21 | | } |
| | | 22 | | |
| | | 23 | | public void Attach(InstanceContext owner) |
| | | 24 | | { |
| | | 25 | | // intentionally left blank |
| | 1906 | 26 | | } |
| | | 27 | | |
| | | 28 | | public void Detach(InstanceContext owner) |
| | | 29 | | { |
| | | 30 | | // intentionally left blank |
| | 1906 | 31 | | } |
| | | 32 | | |
| | 1908 | 33 | | public object GetService(Type serviceType) => _serviceScope.ServiceProvider.GetService(serviceType); |
| | | 34 | | |
| | 1906 | 35 | | public void Dispose() => _serviceScope?.Dispose(); |
| | | 36 | | |
| | 4 | 37 | | public object GetKeyedService(Type serviceType, object serviceKey) => KeyedServiceProvider.GetKeyedService(s |
| | | 38 | | |
| | 0 | 39 | | public object GetRequiredKeyedService(Type serviceType, object serviceKey) => KeyedServiceProvider.GetRequir |
| | | 40 | | } |
| | | 41 | | |
| | | 42 | | private delegate object GetInstanceDelegate(InstanceContext instanceContext); |
| | | 43 | | private delegate void ReleaseInstanceDelegate(InstanceContext instanceContext, object instance); |
| | | 44 | | |
| | | 45 | | private readonly IServiceProvider _serviceProvider; |
| | | 46 | | private readonly IServiceProviderIsService _serviceProviderIsService; |
| | | 47 | | private readonly Type _serviceType; |
| | | 48 | | private GetInstanceDelegate _getInstanceDelegate; |
| | | 49 | | private ReleaseInstanceDelegate _releaseInstanceDelegate; |
| | | 50 | | |
| | 503 | 51 | | public DependencyInjectionWithLegacyFallbackInstanceProvider(IServiceProvider serviceProvider, Type serviceType) |
| | | 52 | | { |
| | 503 | 53 | | _serviceProvider = serviceProvider ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameo |
| | 503 | 54 | | _serviceType = serviceType ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(servic |
| | | 55 | | |
| | 503 | 56 | | _serviceProviderIsService = _serviceProvider.GetRequiredService<IServiceProviderIsService>(); |
| | 503 | 57 | | _getInstanceDelegate = GetInstanceFromDIWithLegacyFallback; |
| | | 58 | | // Defaults to ReleaseInstanceLegacy |
| | 503 | 59 | | _releaseInstanceDelegate = ReleaseInstanceLegacy; |
| | 503 | 60 | | } |
| | | 61 | | |
| | | 62 | | public object GetInstance(InstanceContext instanceContext) |
| | 0 | 63 | | => GetInstance(instanceContext, null); |
| | | 64 | | |
| | | 65 | | public object GetInstance(InstanceContext instanceContext, Message message) |
| | 2389 | 66 | | => _getInstanceDelegate(instanceContext); |
| | | 67 | | |
| | | 68 | | public void ReleaseInstance(InstanceContext instanceContext, object instance) |
| | 2387 | 69 | | => _releaseInstanceDelegate(instanceContext, instance); |
| | | 70 | | |
| | | 71 | | public void ReleaseInstanceLegacy(InstanceContext instanceContext, object instance) |
| | 481 | 72 | | => (instance as IDisposable)?.Dispose(); |
| | | 73 | | |
| | | 74 | | public void ReleaseServiceScope(InstanceContext instanceContext, object instance) |
| | | 75 | | { |
| | 1906 | 76 | | var extension = GetScopedServiceProviderExtension(instanceContext); |
| | 1906 | 77 | | instanceContext.Extensions.Remove(extension); |
| | 1906 | 78 | | extension.Dispose(); |
| | 1906 | 79 | | } |
| | | 80 | | |
| | | 81 | | private object GetInstanceFromDIWithLegacyFallback(InstanceContext instanceContext) |
| | | 82 | | { |
| | 416 | 83 | | if (_serviceProviderIsService.IsService(_serviceType)) |
| | | 84 | | { |
| | 146 | 85 | | var extension = new ScopedServiceProviderExtension(_serviceProvider); |
| | 146 | 86 | | instanceContext.Extensions.Add(extension); |
| | | 87 | | |
| | | 88 | | // Overwrite _getInstanceDelegate so subsequent calls pull instance from ServiceScope |
| | 146 | 89 | | _getInstanceDelegate = GetInstanceFromDI; |
| | | 90 | | // Overwrite _releaseInstanceDelegate so subsequent calls release the ServiceScope and thus instance pul |
| | 146 | 91 | | _releaseInstanceDelegate = ReleaseServiceScope; |
| | | 92 | | |
| | 146 | 93 | | return extension.GetService(_serviceType); |
| | | 94 | | } |
| | | 95 | | |
| | 270 | 96 | | if (InvokerUtil.HasDefaultConstructor(_serviceType)) |
| | | 97 | | { |
| | 269 | 98 | | CreateInstanceDelegate createInstance = InvokerUtil.GenerateCreateInstanceDelegate(_serviceType); |
| | 751 | 99 | | _getInstanceDelegate = _ => createInstance(); |
| | | 100 | | } |
| | | 101 | | else // Fallback to throwing exception if not in DI and no default constructor |
| | | 102 | | { |
| | 2 | 103 | | _getInstanceDelegate = _ => throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperati |
| | 2 | 104 | | SR.Format(SR.SFxNoDefaultConstructor, _serviceType.FullName))); |
| | | 105 | | } |
| | | 106 | | |
| | 270 | 107 | | return _getInstanceDelegate(instanceContext); |
| | | 108 | | } |
| | | 109 | | |
| | | 110 | | private object GetInstanceFromDI(InstanceContext instanceContext) |
| | | 111 | | { |
| | 1760 | 112 | | ScopedServiceProviderExtension extension = GetScopedServiceProviderExtension(instanceContext); |
| | 1760 | 113 | | if (extension == null) |
| | | 114 | | { |
| | 1760 | 115 | | extension = new ScopedServiceProviderExtension(_serviceProvider); |
| | 1760 | 116 | | instanceContext.Extensions.Add(extension); |
| | | 117 | | } |
| | | 118 | | |
| | 1760 | 119 | | return extension.GetService(_serviceType); |
| | | 120 | | } |
| | | 121 | | |
| | | 122 | | private static ScopedServiceProviderExtension GetScopedServiceProviderExtension(InstanceContext instanceContext) |
| | 3666 | 123 | | => instanceContext.Extensions.Find<ScopedServiceProviderExtension>(); |
| | | 124 | | } |
| | | 125 | | } |