• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NetFabric / NetFabric.CodeAnalysis / 6470493102

10 Oct 2023 02:08PM UTC coverage: 73.784%. First build
6470493102

push

github

aalmada
Support more targets

323 of 452 branches covered (0.0%)

Branch coverage included in aggregate %.

5 of 5 new or added lines in 1 file covered. (100.0%)

648 of 864 relevant lines covered (75.0%)

20.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.52
/src/NetFabric.Reflection/Reflection/TypeExtensions.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Diagnostics.CodeAnalysis;
4
using System.Numerics;
5
using System.Reflection;
6
using Microsoft.VisualBasic;
7

8
// ReSharper disable LoopCanBeConvertedToQuery
9

10
namespace NetFabric.Reflection;
11

12
public static partial class TypeExtensions
13
{
14
    /// <summary>
15
    /// Determines whether the specified <see cref="Type"/> implements a specified interface and, if so, provides information about generic type arguments.
16
    /// </summary>
17
    /// <param name="type">The <see cref="Type"/> to check for interface implementation.</param>
18
    /// <param name="interfaceType">The <see cref="Type"/> of the interface to check for implementation.</param>
19
    /// <param name="genericArguments">
20
    /// When the method returns <c>true</c>, this parameter contains an array of <see cref="Type"/> objects representing the generic type arguments
21
    /// that make the implementation of the specified interface. If the type does not implement the interface or if the interface is non-generic,
22
    /// this parameter is set to <c>null</c>.
23
    /// </param>
24
    /// <returns>
25
    ///   <c>true</c> if the specified <see cref="Type"/> implements the specified interface; otherwise, <c>false</c>.
26
    /// </returns>
27
    public static bool ImplementsInterface(this Type type, Type interfaceType, [NotNullWhen(true)] out Type[]? genericArguments)
28
    {
29
        if (!interfaceType.IsGenericType)
143✔
30
        {
31
            genericArguments = Type.EmptyTypes;
103✔
32
            return interfaceType.IsAssignableFrom(type);
103✔
33
        }
34

35
        if (type.IsGenericType && type.GetGenericTypeDefinition() == interfaceType.GetGenericTypeDefinition())
40✔
36
        {
37
            genericArguments = type.GetGenericArguments();
8✔
38
            return true;
8✔
39
        }
40

41
        foreach (var @interface in type.GetInterfaces())
92✔
42
        {
43
            if (ImplementsInterface(@interface, interfaceType, out genericArguments))
18✔
44
                return true;
8✔
45
        }
46

47
        genericArguments = default;
24✔
48
        return false;
24✔
49
    }
50

51
    const BindingFlags PublicInstance =
52
        BindingFlags.Public | BindingFlags.Instance;
53

54
    internal static PropertyInfo? GetPublicReadIndexer(this Type type, params Type[] parameterTypes)
55
    {
56
        foreach (var property in type.GetProperties(PublicInstance))
30✔
57
        {
58
            if (property.GetGetMethod() is not null && 
9✔
59
                SequenceEqual(property.GetIndexParameters(), parameterTypes))
9✔
60
            {
61
                return property;
6✔
62
            }
63
        }
64

65
        if (type.IsInterface)
3✔
66
        {
67
            foreach(var @interface in type.GetInterfaces())
3✔
68
            {
69
                var indexer = GetPublicReadIndexer(@interface, parameterTypes);
1✔
70
                if (indexer is not null)
1!
71
                    return indexer;
1✔
72
            }
73
        }
74

75
        return default;
2✔
76
    }
77

78
    internal static PropertyInfo? GetPublicReadProperty(this Type type, string name)
79
    {
80
        foreach (var property in type.GetProperties(PublicInstance))
513✔
81
        {
82
            if (property.Name == name && 
182✔
83
            property.GetGetMethod() is not null)
182✔
84
            {
85
                return property;
107✔
86
            }
87
        }
88

89
        if (type.IsInterface)
21✔
90
        {
91
            foreach(var @interface in type.GetInterfaces())
11✔
92
            {
93
                var indexer = GetPublicReadProperty(@interface, name);
2✔
94
                if (indexer is not null)
2✔
95
                    return indexer;
1✔
96
            }
97
        }
98

99
        return default;
20✔
100
    }
101

102
    //internal static PropertyInfo? GetExplicitReadProperty(this Type type, Type interfaceType, string name)
103
    //{
104
    //    var interfaceMap = type.GetInterfaceMap(interfaceType);
105

106
    //    var getMethodName = $"get_{name}";
107
    //    foreach (var methodInfo in interfaceMap.InterfaceMethods)
108
    //    {
109
    //        if (methodInfo.Name == getMethodName)
110
    //        {
111
    //            return interfaceType.GetProperty(name);
112
    //        }
113
    //    }  
114

115
    //    return default;
116
    //}
117

118
    internal static MethodInfo? GetPublicMethod(this Type type, string name, params Type[] types)
119
    {
120
        var method = type.GetMethod(name, PublicInstance, null, types, null);
436✔
121
        if (method is not null)
436✔
122
            return method;
292✔
123

124
        if (type.IsInterface)
144✔
125
        {
126
            foreach(var @interface in type.GetInterfaces())
157✔
127
            {
128
                method = GetPublicMethod(@interface, name);
45✔
129
                if (method is not null)
45✔
130
                    return method;
23✔
131
            }
132
        }            
133

134
        return default;
121✔
135
    }
136

137
    //internal static MethodInfo? GetExplicitMethod(this Type type, Type interfaceType, string name, params Type[] types)
138
    //{
139
    //    var interfaceMap = type.GetInterfaceMap(interfaceType);
140
    //    var interfaceMethods = interfaceMap.InterfaceMethods;
141
    //    for (int index = 0; index < interfaceMethods.Length; index++)
142
    //    {
143
    //        if (interfaceMethods[index].Name == name)
144
    //        {
145
    //            var methodInfo = interfaceMap.TargetMethods[index];
146
    //            if(SequenceEqual(methodInfo.GetParameters(), types))
147
    //                return methodInfo;
148
    //        }
149
    //    }
150

151
    //    return default;
152
    //}
153

154
    static bool SequenceEqual(ParameterInfo[] parameters, Type[] types)
155
    {
156
        if (parameters.Length != types.Length)
9✔
157
            return false;
2✔
158

159
        // ReSharper disable once LoopCanBeConvertedToQuery
160
        for (var index = 0; index < parameters.Length; index++)
26✔
161
        {
162
            if (parameters[index].ParameterType != types[index])
7✔
163
                return false;
1✔
164
        }
165

166
        return true;
6✔
167
    }
168

169
    /// <summary>
170
    /// Determines whether the specified <see cref="Type"/> represents a <see cref="Span{T}"/> or <see cref="ReadOnlySpan{T}"/>.
171
    /// </summary>
172
    /// <param name="type">The <see cref="Type"/> to check for <see cref="Span{T}"/> or <see cref="ReadOnlySpan{T}"/>.</param>
173
    /// <returns>
174
    ///   <c>true</c> if the specified <see cref="Type"/> represents a <see cref="Span{T}"/> or <see cref="ReadOnlySpan{T}"/>;
175
    ///   otherwise, <c>false</c>.
176
    /// </returns>
177
    public static bool IsSpanOrReadOnlySpan(this Type type)
178
    {
179
        if (type.IsGenericType)
83✔
180
        {
181
            var genericTypeDefinition = type.GetGenericTypeDefinition();
73✔
182
            return genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>);
73✔
183
        }
184

185
        return false;
10✔
186
    }
187

188
    /// <summary>
189
    /// Determines whether the specified <see cref="Type"/> represents an integer type.
190
    /// </summary>
191
    /// <param name="type">The <see cref="Type"/> to check for integer type.</param>
192
    /// <returns>
193
    ///   <c>true</c> if the specified <see cref="Type"/> represents an integer type; otherwise, <c>false</c>.
194
    /// </returns>
195
    /// <remarks>
196
    /// Starting from .NET 7, this method checks if the <see cref="Type"/> implements the <see cref="System.Numerics.IBinaryInteger{T}"/> interface,
197
    /// which indicates support for binary integer operations.
198
    /// </remarks>
199
    public static bool IsIntegerType(this Type type)
200
    {
201
        if (type == typeof(SByte) || 
15!
202
            type == typeof(Byte) || 
15✔
203
            type == typeof(Int16) || 
15✔
204
            type == typeof(UInt16) || 
15✔
205
            type == typeof(Int32) || 
15✔
206
            type == typeof(UInt32) || 
15✔
207
            type == typeof(Int64) || 
15✔
208
            type == typeof(UInt64)) 
15✔
209
        {
210
            return true;
15✔
211
        }
212

213
#if NET7_0_OR_GREATER
214
        if (type.ImplementsInterface(typeof(IBinaryInteger<>), out var arguments) && 
215
            arguments.Length == 1 &&
216
            arguments[0] == type)
217
        {
218
            return true;
219
        }
220
#endif
221

222
        return false;
×
223
    }
224

225
    /// <summary>
226
    /// Determines whether the specified <see cref="Type"/> represents a floating-point numeric type.
227
    /// </summary>
228
    /// <param name="type">The <see cref="Type"/> to check for a floating-point numeric type.</param>
229
    /// <returns>
230
    ///   <c>true</c> if the specified <see cref="Type"/> represents a floating-point numeric type; otherwise, <c>false</c>.
231
    /// </returns>
232
    /// <remarks>
233
    /// Starting from .NET 7, this method compares the <see cref="Type"/> to the <see cref="System.Numerics.IFloatingPoint{T}"/> interface,
234
    /// which indicates support for floating-point numeric operations.
235
    /// </remarks>
236
    public static bool IsFloatingPointType(this Type type)
237
    {
238
        if (
×
239
#if NET5_0_OR_GREATER
×
240
            type == typeof(Half) ||
×
241
#endif
×
242
            type == typeof(float) || 
×
243
            type == typeof(double) || 
×
244
            type == typeof(decimal))
×
245
        {
246
            return true;
×
247
        }
248

249
#if NET7_0_OR_GREATER
250
        if (type.ImplementsInterface(typeof(IFloatingPoint<>), out var arguments) && 
251
            arguments.Length == 1 &&
252
            arguments[0] == type)
253
        {
254
            return true;
255
        }
256
#endif
257

258
        return false;
×
259
    }
260

261
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc