< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.MessageHeader<T>
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/MessageHeaderT.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 16
Coverable lines: 16
Total lines: 174
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%110%
.ctor(...)100%110%
.ctor(...)100%110%
GetGenericArgument()100%110%
GetUntypedHeader(...)100%110%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/MessageHeaderT.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.Reflection;
 7using System.Threading;
 8using CoreWCF.Channels;
 9
 10namespace CoreWCF
 11{
 12    public class MessageHeader<T>
 13    {
 014        public MessageHeader()
 15        {
 016        }
 17
 18        public MessageHeader(T content)
 019            : this(content, false, "", false)
 20        {
 021        }
 22
 023        public MessageHeader(T content, bool mustUnderstand, string actor, bool relay)
 24        {
 025            Content = content;
 026            MustUnderstand = mustUnderstand;
 027            Actor = actor;
 028            Relay = relay;
 029        }
 30
 031        public string Actor { get; set; }
 32
 033        public T Content { get; set; }
 34
 035        public bool MustUnderstand { get; set; }
 36
 037        public bool Relay { get; set; }
 38
 39        internal Type GetGenericArgument()
 40        {
 041            return typeof(T);
 42        }
 43
 44        public MessageHeader GetUntypedHeader(string name, string ns)
 45        {
 046            return MessageHeader.CreateHeader(name, ns, Content, MustUnderstand, Actor, Relay);
 47        }
 48    }
 49
 50    // problem: creating / getting content / settings content on a MessageHeader<T> given the type at runtime
 51    // require reflection.
 52    // solution: This class creates a cache of adapters that provide an untyped wrapper over a particular
 53    // MessageHeader<T> instantiation.
 54    // better solution: implement something like "IUntypedTypedHeader" that has a "object Content" property,
 55    // privately implement this on TypedHeader, and then just use that iface to operation on the header (actually
 56    // you'd still have the creation problem...).  the issue with that is you now have a new public interface
 57    internal abstract class TypedHeaderManager
 58    {
 59        private static readonly Dictionary<Type, TypedHeaderManager> s_cache = new Dictionary<Type, TypedHeaderManager>(
 60        private static readonly ReaderWriterLockSlim s_cacheLock = new ReaderWriterLockSlim();
 61        private static readonly Type s_genericAdapterType = typeof(GenericAdapter<>);
 62
 63        internal static object Create(Type t, object content, bool mustUnderstand, bool relay, string actor)
 64        {
 65            return GetTypedHeaderManager(t).Create(content, mustUnderstand, relay, actor);
 66        }
 67
 68        internal static object GetContent(Type t, object typedHeaderInstance, out bool mustUnderstand, out bool relay, o
 69        {
 70            return GetTypedHeaderManager(t).GetContent(typedHeaderInstance, out mustUnderstand, out relay, out actor);
 71        }
 72
 73        internal static Type GetMessageHeaderType(Type contentType)
 74        {
 75            return GetTypedHeaderManager(contentType).GetMessageHeaderType();
 76        }
 77        internal static Type GetHeaderType(Type headerParameterType)
 78        {
 79            if (headerParameterType.GetTypeInfo().IsGenericType && headerParameterType.GetGenericTypeDefinition() == typ
 80            {
 81                return headerParameterType.GetGenericArguments()[0];
 82            }
 83
 84            return headerParameterType;
 85        }
 86
 87        private static TypedHeaderManager GetTypedHeaderManager(Type t)
 88        {
 89            TypedHeaderManager result = null;
 90
 91            bool readerLockHeld = false;
 92            bool writerLockHeld = false;
 93            try
 94            {
 95                try
 96                {
 97                }
 98                finally
 99                {
 100                    s_cacheLock.TryEnterUpgradeableReadLock(Timeout.Infinite);
 101                    readerLockHeld = true;
 102                }
 103                if (!s_cache.TryGetValue(t, out result))
 104                {
 105                    s_cacheLock.TryEnterWriteLock(Timeout.Infinite);
 106                    writerLockHeld = true;
 107                    if (!s_cache.TryGetValue(t, out result))
 108                    {
 109                        result = (TypedHeaderManager)Activator.CreateInstance(s_genericAdapterType.MakeGenericType(t));
 110                        s_cache.Add(t, result);
 111                    }
 112                }
 113            }
 114            finally
 115            {
 116                if (writerLockHeld)
 117                {
 118                    s_cacheLock.ExitWriteLock();
 119                }
 120                if (readerLockHeld)
 121                {
 122                    s_cacheLock.ExitUpgradeableReadLock();
 123                }
 124            }
 125
 126            return result;
 127        }
 128
 129        protected abstract object Create(object content, bool mustUnderstand, bool relay, string actor);
 130        protected abstract object GetContent(object typedHeaderInstance, out bool mustUnderstand, out bool relay, out st
 131        protected abstract Type GetMessageHeaderType();
 132
 133        private class GenericAdapter<T> : TypedHeaderManager
 134        {
 135            protected override object Create(object content, bool mustUnderstand, bool relay, string actor)
 136            {
 137                MessageHeader<T> header = new MessageHeader<T>
 138                {
 139                    Content = (T)content,
 140                    MustUnderstand = mustUnderstand,
 141                    Relay = relay,
 142                    Actor = actor
 143                };
 144                return header;
 145            }
 146
 147            protected override object GetContent(object typedHeaderInstance, out bool mustUnderstand, out bool relay, ou
 148            {
 149                mustUnderstand = false;
 150                relay = false;
 151                actor = null;
 152                if (typedHeaderInstance == null)
 153                {
 154                    return null;
 155                }
 156
 157                if (!(typedHeaderInstance is MessageHeader<T> header))
 158                {
 159                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(nameof(typedHeaderIn
 160                }
 161
 162                mustUnderstand = header.MustUnderstand;
 163                relay = header.Relay;
 164                actor = header.Actor;
 165                return header.Content;
 166            }
 167
 168            protected override Type GetMessageHeaderType()
 169            {
 170                return typeof(MessageHeader<T>);
 171            }
 172        }
 173    }
 174}