Skip to content

Commit a797811

Browse files
committed
Move GetAllInstanceMethods method to TypeUtil
1 parent 70320e7 commit a797811

File tree

6 files changed

+41
-66
lines changed

6 files changed

+41
-66
lines changed

src/Castle.Core.Tests/DynamicProxy.Tests/GenericInterfaceProxyTestCase.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Castle.DynamicProxy.Tests
1717
using System;
1818
using System.Collections.Generic;
1919

20-
using Castle.DynamicProxy.Generators;
20+
using Castle.DynamicProxy.Internal;
2121
using Castle.DynamicProxy.Tests.GenInterfaces;
2222
using Castle.DynamicProxy.Tests.Interceptors;
2323
using Castle.DynamicProxy.Tests.Interfaces;
@@ -414,16 +414,17 @@ public void TypeGetMethodsIsStable()
414414
[Test(Description =
415415
"There is a strange CLR bug resulting from our loading the tokens of methods in generic types. " +
416416
"This test ensures we correctly work around it.")]
417-
public void MethodFinderIsStable()
417+
public void GetAllInstanceMethodsIsStable()
418418
{
419419
ProxyWithGenInterfaceWithBase();
420-
Assert.AreEqual(4, MethodFinder.GetAllInstanceMethods(typeof(IGenInterfaceHierarchyBase<int>)).Length);
420+
Assert.AreEqual(4, typeof(IGenInterfaceHierarchyBase<int>).GetAllInstanceMethods().Length);
421421
}
422422

423423
#if FEATURE_APPDOMAIN
424424
[Test(Description =
425425
"There is a strange CLR bug resulting from our loading the tokens of methods in generic types. " +
426-
"This test ensures we do not trigger it across AppDomains. If we do, MethodFinder must provide a cross-AppDomain workaround.")]
426+
"This test ensures we do not trigger it across AppDomains. " +
427+
"If we do, GetAllInstanceMethods must provide a cross-AppDomain workaround.")]
427428
public void TypeGetMethodsIsStableInDifferentAppDomains()
428429
{
429430
ProxyWithGenInterfaceWithBase();

src/Castle.Core.Tests/DynamicProxy.Tests/MethodFinderTestCase.cs renamed to src/Castle.Core.Tests/DynamicProxy.Tests/TypeUtilTestCase.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,35 @@ namespace Castle.DynamicProxy.Tests
1717
using System.Linq;
1818
using System.Reflection;
1919

20-
using Castle.DynamicProxy.Generators;
20+
using Castle.DynamicProxy.Internal;
2121

2222
using NUnit.Framework;
2323

2424
[TestFixture]
25-
public class MethodFinderTestCase
25+
public class TypeUtilTestCase
2626
{
2727
[Test]
28-
public void GetMethodsForPublicAndNonPublic()
28+
public void GetAllInstanceMethods_GetsPublicAndNonPublicMethods()
2929
{
3030
MethodInfo[] methods =
31-
MethodFinder.GetAllInstanceMethods(typeof(object));
31+
typeof(object).GetAllInstanceMethods();
3232
MethodInfo[] realMethods =
3333
typeof(object).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
3434
CollectionAssert.AreEquivalent(realMethods, methods);
3535
}
3636

37-
// The test above suggests that `MethodFinder.GetAllInstanceMethods` and `Type.GetMethods`
37+
// The test above suggests that `TypeUtil.GetAllInstanceMethods` and `Type.GetMethods`
3838
// can be used interchangeably, but this is not always the case. See the test(s) below and
39-
// `GenericInterfaceProxyTestCase.MethodFinderIsStable` for cases where the two methods
39+
// `GenericInterfaceProxyTestCase.GetAllInstanceMethodsIsStable` for cases where the two methods
4040
// may produce different results.
4141

4242
#if NET5_0_OR_GREATER
4343

4444
[Test]
45-
public void NoDuplicatesForMethodWithCovariantReturnType()
45+
public void GetAllInstanceMethods_NoDuplicatesForMethodWithCovariantReturnType()
4646
{
4747
MethodInfo[] methods =
48-
MethodFinder.GetAllInstanceMethods(typeof(Derived));
48+
typeof(Derived).GetAllInstanceMethods();
4949
MethodInfo[] realMethods =
5050
typeof(Derived).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
5151
CollectionAssert.AreNotEquivalent(realMethods, methods);

src/Castle.Core/DynamicProxy/Contributors/MembersCollector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void CollectEvents()
7272

7373
void CollectMethods()
7474
{
75-
var methodsFound = MethodFinder.GetAllInstanceMethods(type);
75+
var methodsFound = type.GetAllInstanceMethods();
7676
foreach (var method in methodsFound)
7777
{
7878
AddMethod(method, true);

src/Castle.Core/DynamicProxy/Generators/MethodFinder.cs

Lines changed: 0 additions & 52 deletions
This file was deleted.

src/Castle.Core/DynamicProxy/Internal/InvocationHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ private static MethodInfo ObtainMethod(MethodInfo proxiedMethod, Type type)
7373
else
7474
{
7575
// NOTE: this implementation sucks, feel free to improve it.
76-
var methods = MethodFinder.GetAllInstanceMethods(type);
76+
var methods = type.GetAllInstanceMethods();
7777
foreach (var method in methods)
7878
{
7979
if (MethodSignatureComparer.Instance.Equals(method.GetBaseDefinition(), proxiedMethod))

src/Castle.Core/DynamicProxy/Internal/TypeUtil.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@ namespace Castle.DynamicProxy.Internal
1717
using System;
1818
using System.Collections.Generic;
1919
using System.Diagnostics;
20+
using System.Linq;
2021
using System.Reflection;
2122
using System.Reflection.Emit;
2223

24+
using Castle.DynamicProxy.Generators;
2325
using Castle.DynamicProxy.Generators.Emitters;
2426

2527
public static class TypeUtil
2628
{
29+
private static readonly Dictionary<Type, MethodInfo[]> instanceMethodsCache = new Dictionary<Type, MethodInfo[]>();
30+
2731
internal static bool IsNullableType(this Type type)
2832
{
2933
return type.IsGenericType &&
@@ -55,6 +59,28 @@ internal static FieldInfo[] GetAllFields(this Type type)
5559
return fields.ToArray();
5660
}
5761

62+
/// <summary>
63+
/// Returns the methods implemented by a type. Use this instead of Type.GetMethods to filter out duplicate MethodInfos
64+
/// sometimes reported by the latter. The test suite documents cases where such duplicates may occur.
65+
/// </summary>
66+
internal static MethodInfo[] GetAllInstanceMethods(this Type type)
67+
{
68+
MethodInfo[] methodsInCache;
69+
70+
lock (instanceMethodsCache)
71+
{
72+
if (!instanceMethodsCache.TryGetValue(type, out methodsInCache))
73+
{
74+
methodsInCache = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
75+
.Distinct(MethodSignatureComparer.Instance)
76+
.ToArray();
77+
instanceMethodsCache.Add(type, methodsInCache);
78+
}
79+
}
80+
81+
return methodsInCache;
82+
}
83+
5884
/// <summary>
5985
/// Returns list of all unique interfaces implemented given types, including their base interfaces.
6086
/// </summary>

0 commit comments

Comments
 (0)