< Summary

Information
Class: Ice.Internal.Patcher.InvokeInfo
Assembly: Ice
File(s): /_/csharp/src/Ice/Internal/Patcher.cs
Tag: 99_23991109993
Line coverage
52%
Covered lines: 11
Uncovered lines: 10
Coverable lines: 21
Total lines: 133
Line coverage: 52.3%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage
75%
Covered methods: 3
Total methods: 4
Method coverage: 75%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
getCount(...)100%1.13150%
invokeAdd(...)100%1.04166.67%
invokeSet(...)100%210%

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
 12        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    {
 16        return (T? v) =>
 17        {
 18            int count = seq.Count;
 19            if (index >= count) // Need to grow the sequence.
 20            {
 21                for (int i = count; i < index; i++)
 22                {
 23                    seq.Add(null);
 24                }
 25                seq.Add(v);
 26            }
 27            else
 28            {
 29                seq[index] = v;
 30            }
 31        };
 32    }
 33
 34    public static System.Action<T?> customSeqReadValue<T>(IEnumerable<T?> seq, int index) where T : Ice.Value
 35    {
 36        return (T? v) =>
 37        {
 38            InvokeInfo info = getInvokeInfo<T>(seq.GetType());
 39            int count = info.getCount(seq);
 40            if (index >= count) // Need to grow the sequence.
 41            {
 42                for (int i = count; i < index; i++)
 43                {
 44                    info.invokeAdd(seq, null);
 45                }
 46                info.invokeAdd(seq, v);
 47            }
 48            else
 49            {
 50                info.invokeSet(seq, index, v);
 51            }
 52        };
 53    }
 54
 55    private static InvokeInfo getInvokeInfo<T>(Type t)
 56    {
 57        lock (_methodTable)
 58        {
 59            if (_methodTable.TryGetValue(t, out InvokeInfo? i))
 60            {
 61                return i;
 62            }
 63
 64            MethodInfo? am = t.GetMethod("Add", [typeof(T)]) ??
 65                throw new Ice.MarshalException("Cannot patch a collection without an Add() method");
 66            PropertyInfo? pi = t.GetProperty("Item") ??
 67                throw new Ice.MarshalException("Cannot patch a collection without an indexer");
 68            MethodInfo? sm = pi.GetSetMethod() ??
 69                throw new Ice.MarshalException("Cannot patch a collection without an indexer to set a value");
 70            pi = t.GetProperty("Count") ??
 71                throw new Ice.MarshalException("Cannot patch a collection without a Count property");
 72            MethodInfo? cm = pi.GetGetMethod() ??
 73                throw new Ice.MarshalException("Cannot patch a collection without a readable Count property");
 74            i = new InvokeInfo(am, sm, cm);
 75            _methodTable.Add(t, i);
 76            return i;
 77        }
 78    }
 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
 132    private static readonly Dictionary<Type, InvokeInfo> _methodTable = new Dictionary<Type, InvokeInfo>();
 133}