< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Dispatcher.InstanceProvider
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Dispatcher/InstanceBehavior.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 8
Coverable lines: 8
Total lines: 281
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 4
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)0%220%
GetInstance(...)100%110%
GetInstance(...)100%110%
ReleaseInstance(...)0%220%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Dispatcher/InstanceBehavior.cs

#LineLine coverage
 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
 4using System;
 5using System.Reflection;
 6using System.Threading.Tasks;
 7using CoreWCF.Channels;
 8using CoreWCF.Diagnostics;
 9using CoreWCF.Runtime;
 10
 11namespace CoreWCF.Dispatcher
 12{
 13    internal class InstanceBehavior
 14    {
 15        private const BindingFlags DefaultBindingFlags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.P
 16        private readonly IInstanceContextInitializer[] _initializers;
 17        private readonly IInstanceProvider _provider;
 18        private readonly InstanceContext _singleton;
 19        private readonly ImmutableDispatchRuntime _immutableRuntime;
 20        private readonly Type _serviceType;
 21
 22        internal InstanceBehavior(DispatchRuntime dispatch, ImmutableDispatchRuntime immutableRuntime)
 23        {
 24            _immutableRuntime = immutableRuntime;
 25            _serviceType = dispatch.Type;
 26            _initializers = EmptyArray<IInstanceContextInitializer>.ToArray(dispatch.InstanceContextInitializers);
 27            _provider = dispatch.InstanceProvider;
 28            _singleton = dispatch.SingletonInstanceContext;
 29            InstanceContextProvider = dispatch.InstanceContextProvider;
 30
 31            if (_provider == null)
 32            {
 33                bool hasDefaultConstructor = dispatch.Type != null && InvokerUtil.HasDefaultConstructor(dispatch.Type);
 34                if (_singleton == null)
 35                {
 36                    if (dispatch.Type != null && (dispatch.Type.GetTypeInfo().IsAbstract || dispatch.Type.GetTypeInfo().
 37                    {
 38                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.SFxSe
 39                    }
 40
 41                    if (!hasDefaultConstructor)
 42                    {
 43                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
 44                            SR.Format(SR.SFxNoDefaultConstructor, dispatch.Type?.FullName ?? "Unknown")));
 45                    }
 46                }
 47
 48                if (!hasDefaultConstructor)
 49                {
 50                    if (_singleton == null || !_singleton.IsWellKnown)
 51                    {
 52                        CreateInstanceDelegate creator = InvokerUtil.GenerateCreateInstanceDelegate(dispatch.Type);
 53                        _provider = new InstanceProvider(creator);
 54                    }
 55                }
 56            }
 57
 58            if (_singleton != null)
 59            {
 60                _singleton.Behavior = this;
 61            }
 62        }
 63
 64        internal IInstanceContextProvider InstanceContextProvider { get; }
 65
 66        internal void AfterReply(ref MessageRpc rpc, ErrorBehavior error)
 67        {
 68            InstanceContext context = rpc.InstanceContext;
 69
 70            if (context != null)
 71            {
 72                try
 73                {
 74                    if (rpc.Operation.ReleaseInstanceAfterCall)
 75                    {
 76                        if (context.State == CommunicationState.Opened)
 77                        {
 78                            context.ReleaseServiceInstance();
 79                        }
 80                    }
 81                }
 82                catch (Exception e)
 83                {
 84                    if (Fx.IsFatal(e))
 85                    {
 86                        throw;
 87                    }
 88                    error.HandleError(e);
 89                }
 90
 91                try
 92                {
 93                    context.UnbindRpc(rpc);
 94                }
 95                catch (Exception e)
 96                {
 97                    if (Fx.IsFatal(e))
 98                    {
 99                        throw;
 100                    }
 101                    error.HandleError(e);
 102                }
 103            }
 104        }
 105
 106        internal bool CanUnload(InstanceContext instanceContext)
 107        {
 108            if (InstanceContextProviderBase.IsProviderSingleton(InstanceContextProvider))
 109            {
 110                return false;
 111            }
 112
 113            if (InstanceContextProviderBase.IsProviderPerCall(InstanceContextProvider) ||
 114                InstanceContextProviderBase.IsProviderSessionful(InstanceContextProvider))
 115            {
 116                return true;
 117            }
 118
 119            //User provided InstanceContextProvider. Call the provider to check for idle.
 120            if (!InstanceContextProvider.IsIdle(instanceContext))
 121            {
 122                InstanceContextProvider.NotifyIdle(InstanceContext.NotifyIdleCallback, instanceContext);
 123                return false;
 124            }
 125            return true;
 126        }
 127
 128        internal async Task EnsureInstanceContextAsync(MessageRpc rpc)
 129        {
 130            if (rpc.InstanceContext == null)
 131            {
 132                rpc.InstanceContext = new InstanceContext(rpc.Host, false)
 133                {
 134                    ServiceThrottle = rpc.ChannelHandler.InstanceContextServiceThrottle
 135                };
 136                rpc.MessageRpcOwnsInstanceContextThrottle = false;
 137            }
 138
 139            rpc.OperationContext.SetInstanceContext(rpc.InstanceContext);
 140            rpc.InstanceContext.Behavior = this;
 141
 142            if (rpc.InstanceContext.State == CommunicationState.Created)
 143            {
 144                Task openTask = null;
 145                lock (rpc.InstanceContext.ThisLock)
 146                {
 147                    if (rpc.InstanceContext.State == CommunicationState.Created)
 148                    {
 149                        var helper = new TimeoutHelper(rpc.Channel.CloseTimeout);
 150                        // awaiting the task outside the lock is safe as OpenAsync will transition the state away from C
 151                        // it returns an uncompleted Task.
 152                        openTask = rpc.InstanceContext.OpenAsync(helper.GetCancellationToken());
 153                        Fx.Assert(rpc.InstanceContext.State != CommunicationState.Created, "InstanceContext.OpenAsync sh
 154                    }
 155                }
 156
 157                await openTask;
 158            }
 159
 160            rpc.InstanceContext.BindRpc(rpc);
 161        }
 162
 163        private static ConstructorInfo GetConstructor(Type type)
 164        {
 165            foreach (ConstructorInfo constructor in type.GetConstructors(DefaultBindingFlags))
 166            {
 167                if (constructor.GetParameters().Length == 0)
 168                {
 169                    return constructor;
 170                }
 171            }
 172            return null;
 173        }
 174
 175        internal object GetInstance(InstanceContext instanceContext)
 176        {
 177            if (_provider == null)
 178            {
 179                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
 180                    SR.Format(SR.SFxNoDefaultConstructor, _serviceType?.FullName ?? "Unknown")));
 181            }
 182
 183            return _provider.GetInstance(instanceContext);
 184        }
 185
 186        internal object GetInstance(InstanceContext instanceContext, Message request)
 187        {
 188            if (_provider == null)
 189            {
 190                throw TraceUtility.ThrowHelperError(new InvalidOperationException(
 191                    SR.Format(SR.SFxNoDefaultConstructor, _serviceType?.FullName ?? "Unknown")), request);
 192            }
 193
 194            return _provider.GetInstance(instanceContext, request);
 195        }
 196
 197        internal void Initialize(InstanceContext instanceContext)
 198        {
 199            OperationContext current = OperationContext.Current;
 200            Message message = current?.IncomingMessage;
 201
 202            if (current != null && current.InternalServiceChannel != null)
 203            {
 204                IContextChannel transparentProxy = (IContextChannel)current.InternalServiceChannel.Proxy;
 205                InstanceContextProvider.InitializeInstanceContext(instanceContext, message, transparentProxy);
 206            }
 207
 208            for (int i = 0; i < _initializers.Length; i++)
 209            {
 210                _initializers[i].Initialize(instanceContext, message);
 211            }
 212        }
 213
 214        internal void EnsureServiceInstance(MessageRpc rpc)
 215        {
 216            if (rpc.Operation.ReleaseInstanceBeforeCall)
 217            {
 218                rpc.InstanceContext.ReleaseServiceInstance();
 219            }
 220
 221            //if (TD.GetServiceInstanceStartIsEnabled())
 222            //{
 223            //    TD.GetServiceInstanceStart(rpc.EventTraceActivity);
 224            //}
 225
 226            rpc.Instance = rpc.InstanceContext.GetServiceInstance(rpc.Request);
 227
 228            //if (TD.GetServiceInstanceStopIsEnabled())
 229            //{
 230            //    TD.GetServiceInstanceStop(rpc.EventTraceActivity);
 231            //}
 232        }
 233
 234        internal void ReleaseInstance(InstanceContext instanceContext, object instance)
 235        {
 236            if (_provider != null)
 237            {
 238                try
 239                {
 240                    _provider.ReleaseInstance(instanceContext, instance);
 241                }
 242                catch (Exception e)
 243                {
 244                    if (Fx.IsFatal(e))
 245                    {
 246                        throw;
 247                    }
 248                    _immutableRuntime.ErrorBehavior.HandleError(e);
 249                }
 250            }
 251        }
 252    }
 253
 254    internal class InstanceProvider : IInstanceProvider
 255    {
 256        private readonly CreateInstanceDelegate _creator;
 257
 0258        internal InstanceProvider(CreateInstanceDelegate creator)
 259        {
 0260            _creator = creator ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(creator));
 0261        }
 262
 263        public object GetInstance(InstanceContext instanceContext)
 264        {
 0265            return _creator();
 266        }
 267
 268        public object GetInstance(InstanceContext instanceContext, Message message)
 269        {
 0270            return _creator();
 271        }
 272
 273        public void ReleaseInstance(InstanceContext instanceContext, object instance)
 274        {
 0275            if (instance is IDisposable dispose)
 276            {
 0277                dispose.Dispose();
 278            }
 0279        }
 280    }
 281}