< Summary

Information
Class: Ice.Internal.Patcher<T>
Assembly: Ice
File(s): /_/csharp/src/Ice/Internal/Patcher.cs
Tag: 99_23991109993
Line coverage
78%
Covered lines: 57
Uncovered lines: 16
Coverable lines: 73
Total lines: 133
Line coverage: 78%
Branch coverage
55%
Covered branches: 11
Total branches: 20
Branch coverage: 55%
Method coverage
88%
Covered methods: 8
Total methods: 9
Method coverage: 88.8%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
arrayReadValue<T>(...)100%11100%
listReadValue<T>(...)100%11100%
customSeqReadValue<T>(...)100%11100%
getInvokeInfo<T>(...)58.33%1212100%
.ctor(...)100%11100%
getCount(...)100%1.13150%
invokeAdd(...)100%1.04166.67%
invokeSet(...)100%210%
.cctor()100%11100%

File(s)

/_/csharp/src/Ice/Internal/Patcher.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using System.Reflection;
 6
 7namespace Ice.Internal;
 8
 9public sealed class Patcher
 10{
 11    public static System.Action<T?> arrayReadValue<T>(T?[] arr, int index) where
 112        T : Ice.Value => (T? v) => arr[index] = v;
 13
 14    public static System.Action<T?> listReadValue<T>(List<T?> seq, int index) where T : Ice.Value
 15    {
 116        return (T? v) =>
 117        {
 118            int count = seq.Count;
 119            if (index >= count) // Need to grow the sequence.
 120            {
 121                for (int i = count; i < index; i++)
 122                {
 023                    seq.Add(null);
 124                }
 125                seq.Add(v);
 126            }
 127            else
 128            {
 029                seq[index] = v;
 130            }
 031        };
 32    }
 33
 34    public static System.Action<T?> customSeqReadValue<T>(IEnumerable<T?> seq, int index) where T : Ice.Value
 35    {
 136        return (T? v) =>
 137        {
 138            InvokeInfo info = getInvokeInfo<T>(seq.GetType());
 139            int count = info.getCount(seq);
 140            if (index >= count) // Need to grow the sequence.
 141            {
 142                for (int i = count; i < index; i++)
 143                {
 044                    info.invokeAdd(seq, null);
 145                }
 146                info.invokeAdd(seq, v);
 147            }
 148            else
 149            {
 050                info.invokeSet(seq, index, v);
 151            }
 052        };
 53    }
 54
 55    private static InvokeInfo getInvokeInfo<T>(Type t)
 56    {
 157        lock (_methodTable)
 58        {
 159            if (_methodTable.TryGetValue(t, out InvokeInfo? i))
 60            {
 161                return i;
 62            }
 63
 164            MethodInfo? am = t.GetMethod("Add", [typeof(T)]) ??
 165                throw new Ice.MarshalException("Cannot patch a collection without an Add() method");
 166            PropertyInfo? pi = t.GetProperty("Item") ??
 167                throw new Ice.MarshalException("Cannot patch a collection without an indexer");
 168            MethodInfo? sm = pi.GetSetMethod() ??
 169                throw new Ice.MarshalException("Cannot patch a collection without an indexer to set a value");
 170            pi = t.GetProperty("Count") ??
 171                throw new Ice.MarshalException("Cannot patch a collection without a Count property");
 172            MethodInfo? cm = pi.GetGetMethod() ??
 173                throw new Ice.MarshalException("Cannot patch a collection without a readable Count property");
 174            i = new InvokeInfo(am, sm, cm);
 175            _methodTable.Add(t, i);
 176            return i;
 77        }
 178    }
 79
 80    private class InvokeInfo
 81    {
 182        public InvokeInfo(MethodInfo am, MethodInfo sm, MethodInfo cm)
 83        {
 184            _addMethod = am;
 185            _setMethod = sm;
 186            _countMethod = cm;
 187        }
 88
 89        internal int getCount(System.Collections.IEnumerable seq)
 90        {
 91            try
 92            {
 193                return (int)_countMethod.Invoke(seq, null)!;
 94            }
 095            catch (System.Exception ex)
 96            {
 097                throw new Ice.MarshalException("Could not read Count property during patching", ex);
 98            }
 199        }
 100
 101        internal void invokeAdd(System.Collections.IEnumerable seq, object? v)
 102        {
 103            try
 104            {
 1105                object?[] arg = new object?[] { v };
 1106                _addMethod.Invoke(seq, arg);
 1107            }
 0108            catch (System.Exception ex)
 109            {
 0110                throw new Ice.MarshalException("Could not invoke Add method during patching", ex);
 111            }
 1112        }
 113
 114        internal void invokeSet(System.Collections.IEnumerable seq, int index, object? v)
 115        {
 116            try
 117            {
 0118                object?[] args = new object?[] { index, v };
 0119                _setMethod.Invoke(seq, args);
 0120            }
 0121            catch (System.Exception ex)
 122            {
 0123                throw new Ice.MarshalException("Could not call indexer during patching", ex);
 124            }
 0125        }
 126
 127        private readonly MethodInfo _addMethod;
 128        private readonly MethodInfo _setMethod;
 129        private readonly MethodInfo _countMethod;
 130    }
 131
 1132    private static readonly Dictionary<Type, InvokeInfo> _methodTable = new Dictionary<Type, InvokeInfo>();
 133}