< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Description.ServiceDescription
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Description/ServiceDescription.cs
Line coverage
65%
Covered lines: 69
Uncovered lines: 37
Coverable lines: 106
Total lines: 345
Line coverage: 65%
Branch coverage
65%
Covered branches: 38
Total branches: 58
Branch coverage: 65.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%11100%
.ctor(...)0%440%
AddBehaviors(...)78.57%141473.33%
GetService()100%110%
GetService(...)50%4483.33%
CreateImplementation()100%22100%
EnsureCredentials()83.33%66100%
EnsureBehaviorAttribute(...)100%22100%
EnsureInvariants()75%4483.33%
GetIServiceBehaviorAttributes(...)100%22100%
SetupSingleton(...)25%4442.85%
SetupSingleton(...)100%44100%
.ctor()100%110%
GetKeyForItem(...)0%220%
ToImplementedContracts()0%220%
GetConfigKey(...)100%110%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Description/ServiceDescription.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.Collections.Generic;
 6using System.Collections.ObjectModel;
 7using System.Diagnostics;
 8using System.Linq;
 9using System.Linq.Expressions;
 10using System.Reflection;
 11using CoreWCF.Collections.Generic;
 12using CoreWCF.Dispatcher;
 13using CoreWCF.Runtime;
 14using Microsoft.Extensions.DependencyInjection;
 15
 16namespace CoreWCF.Description
 17{
 18    public class ServiceDescription
 19    {
 20        private string _configurationName;
 21        private XmlName _serviceName;
 22
 118223        public ServiceDescription() { }
 24
 025        public ServiceDescription(IEnumerable<ServiceEndpoint> endpoints) : this()
 26        {
 027            if (endpoints == null)
 28            {
 029                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(endpoints));
 30            }
 31
 032            foreach (ServiceEndpoint endpoint in endpoints)
 33            {
 034                Endpoints.Add(endpoint);
 35            }
 036        }
 37
 38        public string Name
 39        {
 40            get
 41            {
 2642                if (_serviceName != null)
 43                {
 244                    return _serviceName.EncodedName;
 45                }
 2446                else if (ServiceType != null)
 47                {
 2448                    return NamingHelper.XmlName(ServiceType.Name);
 49                }
 50                else
 51                {
 052                    return NamingHelper.DefaultServiceName;
 53                }
 54            }
 55            set
 56            {
 457                if (string.IsNullOrEmpty(value))
 58                {
 059                    _serviceName = null;
 60                }
 61                else
 62                {
 63                    // the XmlName ctor validate the value
 464                    _serviceName = new XmlName(value, true /*isEncoded*/);
 65                }
 466            }
 67        }
 68
 61569        public string Namespace { get; set; } = NamingHelper.DefaultNamespace;
 70
 361771        internal IServiceProvider ServiceProvider { get; set; }
 72
 73        // This was KeyedByTypeCollection, maybe change to Collection<IServiceBehavior>
 1572774        public KeyedByTypeCollection<IServiceBehavior> Behaviors { get; } = new KeyedByTypeCollection<IServiceBehavior>(
 75
 76        public string ConfigurationName
 77        {
 078            get { return _configurationName; }
 79            set
 80            {
 58781                _configurationName = value ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(va
 58782            }
 83        }
 84
 931785        public ServiceEndpointCollection Endpoints { get; } = new ServiceEndpointCollection();
 86
 187287        public Type ServiceType { get; set; }
 88
 89        internal static void AddBehaviors<TService>(ServiceDescription serviceDescription, IEnumerable<IServiceBehavior>
 90        {
 58791            TypeLoader<TService>.ApplyServiceInheritance<IServiceBehavior, KeyedByTypeCollection<IServiceBehavior>>(
 58792                serviceDescription.Behaviors, GetIServiceBehaviorAttributes);
 93
 58794            if (injectedBehaviors != null)
 95            {
 96                // Only add IServiceBehavior from DI if concrete type not already added
 97                // TODO: Add logging to state when an injected behavior has been skipped
 248698                foreach(var behavior in injectedBehaviors)
 99                {
 660100                    if (!serviceDescription.Behaviors.Contains(behavior.GetType()))
 101                    {
 658102                        serviceDescription.Behaviors.Add(behavior);
 103                    }
 104                }
 105            }
 106
 587107            ServiceBehaviorAttribute serviceBehavior = EnsureBehaviorAttribute(serviceDescription);
 108
 587109            if (serviceBehavior.Name != null)
 110            {
 0111                serviceDescription.Name = new XmlName(serviceBehavior.Name).EncodedName;
 112            }
 113
 587114            if (serviceBehavior.Namespace != null)
 115            {
 0116                serviceDescription.Namespace = serviceBehavior.Namespace;
 117            }
 118
 587119            if (string.IsNullOrEmpty(serviceBehavior.ConfigurationName))
 120            {
 587121                serviceDescription.ConfigurationName = typeof(TService).FullName;
 122            }
 123            else
 124            {
 0125                serviceDescription.ConfigurationName = serviceBehavior.ConfigurationName;
 126            }
 0127        }
 128
 129        public static ServiceDescription GetService<TService>() where TService : class
 130        {
 131            // TODO: Make ServiceDescription generic?
 0132            var description = new ServiceDescription
 0133            {
 0134                ServiceType = typeof(TService)
 0135            };
 136
 0137            AddBehaviors<TService>(description);
 0138            SetupSingleton(description, (TService)null);
 0139            return description;
 140        }
 141
 142        public static ServiceDescription GetService<TService>(TService serviceImplementation) where TService : class
 143        {
 4144            if (serviceImplementation == null)
 145            {
 0146                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serviceImplementation));
 147            }
 148
 4149            ServiceDescription description = new ServiceDescription
 4150            {
 4151                // TODO: What if the concrete type is different that the generic type?
 4152                ServiceType = typeof(TService) //serviceImplementation.GetType();
 4153            };
 154
 4155            if (serviceImplementation is IServiceBehavior behavior)
 156            {
 0157                description.Behaviors.Add(behavior);
 158            }
 159
 4160            AddBehaviors<TService>(description);
 4161            SetupSingleton(description, serviceImplementation);
 4162            return description;
 163        }
 164
 165        internal static TService CreateImplementation<TService>() where TService : class
 166        {
 75167            if (!InvokerUtil.HasDefaultConstructor(typeof(TService)))
 168            {
 1169                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
 1170                    SR.Format(SR.SFxNoDefaultConstructor, typeof(TService).FullName)));
 171            }
 172
 74173            return (TService)InvokerUtil.GenerateCreateInstanceDelegate(typeof(TService))();
 174        }
 175
 176        //internal static object CreateImplementation(Type serviceType)
 177        //{
 178        //    var constructors = serviceType.GetConstructors(TypeLoader.DefaultBindingFlags);
 179        //    ConstructorInfo constructor = null;
 180        //    foreach (var constr in constructors)
 181        //    {
 182        //        if (constr.GetParameters().Length == 0)
 183        //        {
 184        //            constructor = constr;
 185        //            break;
 186        //        }
 187        //    }
 188
 189        //    if (constructor == null)
 190        //    {
 191        //        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
 192        //            SR.SFxNoDefaultConstructor));
 193        //    }
 194
 195        //    return constructor.Invoke(null, null);
 196        //}
 197
 198        internal ServiceCredentials EnsureCredentials()
 199        {
 17200            ServiceCredentials c = Behaviors.Find<ServiceCredentials>();
 201
 17202            if (c == null)
 203            {
 8204                c = ServiceProvider?.GetRequiredService<ServiceCredentials>() ?? new ServiceCredentials();
 8205                Behaviors.Add(c);
 206            }
 207
 17208            return c;
 209        }
 210
 211        private static ServiceBehaviorAttribute EnsureBehaviorAttribute(ServiceDescription description)
 212        {
 591213            ServiceBehaviorAttribute attr = description.Behaviors.Find<ServiceBehaviorAttribute>();
 214
 591215            if (attr == null)
 216            {
 247217                attr = new ServiceBehaviorAttribute();
 247218                description.Behaviors.Insert(0, attr);
 219            }
 220
 591221            return attr;
 222        }
 223
 224        // This method ensures that the description object graph is structurally sound and that none
 225        // of the fundamental SFx framework assumptions have been violated.
 226        internal void EnsureInvariants()
 227        {
 2434228            for (int i = 0; i < Endpoints.Count; i++)
 229            {
 641230                ServiceEndpoint endpoint = Endpoints[i];
 641231                if (endpoint == null)
 232                {
 0233                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.AChannelS
 234                }
 641235                endpoint.EnsureInvariants();
 236            }
 576237        }
 238
 239        private static void GetIServiceBehaviorAttributes(Type currentServiceType, KeyedByTypeCollection<IServiceBehavio
 240        {
 3138241            foreach (IServiceBehavior behaviorAttribute in ServiceReflector.GetCustomAttributes(currentServiceType, type
 242            {
 340243                behaviors.Add(behaviorAttribute);
 244            }
 1229245        }
 246
 247        internal static void SetupSingleton<TService>(ServiceDescription serviceDescription, TService implementation) wh
 248        {
 4249            ServiceBehaviorAttribute serviceBehavior = EnsureBehaviorAttribute(serviceDescription);
 4250            if (serviceBehavior.InstanceContextMode == InstanceContextMode.Single)
 251            {
 0252                if (implementation == null)
 253                {
 254                    // implementation will only be null if not provided using DI
 0255                    implementation = CreateImplementation<TService>();
 0256                    serviceBehavior.SetHiddenSingleton(implementation);
 257                }
 258                else
 259                {
 0260                    serviceBehavior.SetWellKnownSingleton(implementation);
 261                }
 262            }
 4263        }
 264
 265        internal static void SetupSingleton<TService>(ServiceDescription serviceDescription, IServiceProvider services) 
 266        {
 583267            ServiceBehaviorAttribute serviceBehavior = serviceDescription.Behaviors.Find<ServiceBehaviorAttribute>();
 268            Debug.Assert(serviceBehavior != null, "EnsureServiceBehavior should have ensured the serviceBehavior");
 269
 583270            if (serviceBehavior.InstanceContextMode == InstanceContextMode.Single)
 271            {
 80272                TService implementation = services.GetService<TService>();
 80273                if (implementation == null)
 274                {
 73275                    implementation = CreateImplementation<TService>();
 72276                    serviceBehavior.SetHiddenSingleton(implementation);
 277                }
 278                else
 279                {
 7280                    serviceBehavior.SetWellKnownSingleton(implementation);
 281                }
 282            }
 510283        }
 284
 285        private class ReflectedContractCollection : KeyedCollection<Type, ContractDescription>
 286        {
 287            public ReflectedContractCollection()
 0288                : base(null, 4)
 289            {
 0290            }
 291
 292            protected override Type GetKeyForItem(ContractDescription item)
 293            {
 0294                if (item == null)
 295                {
 0296                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(item));
 297                }
 298
 0299                return item.ContractType;
 300            }
 301
 302            public IDictionary<string, ContractDescription> ToImplementedContracts()
 303            {
 0304                Dictionary<string, ContractDescription> implementedContracts = new Dictionary<string, ContractDescriptio
 0305                foreach (ContractDescription contract in Items)
 306                {
 0307                    implementedContracts.Add(GetConfigKey(contract), contract);
 308                }
 0309                return implementedContracts;
 310            }
 311
 312            internal static string GetConfigKey(ContractDescription contract)
 313            {
 0314                return contract.ConfigurationName;
 315            }
 316        }
 317    }
 318
 319    internal class ServiceDescription<TService> : ServiceDescription where TService : class
 320    {
 321        public ServiceDescription(IEnumerable<IServiceBehavior> injectedBehaviors, IServiceProvider services)
 322        {
 323            ServiceType = typeof(TService);
 324            ServiceProvider = services;
 325            // Clone IServiceBehavior DI services implementing ICloneable to allow per service override.
 326            var behaviors = injectedBehaviors.ToList();
 327
 328            if (services is IKeyedServiceProvider keyedServiceProvider)
 329            {
 330                behaviors.AddRange(keyedServiceProvider.GetKeyedServices<IServiceBehavior>(ServiceType));
 331            }
 332
 333            for (int i = 0; i < behaviors.Count; i++)
 334            {
 335                if(behaviors[i] is ICloneable cloneable)
 336                {
 337                    behaviors[i] = (IServiceBehavior)cloneable.Clone();
 338                }
 339            }
 340
 341            AddBehaviors<TService>(this, behaviors);
 342            SetupSingleton<TService>(this, services);
 343        }
 344    }
 345}