Skip to content

Commit f576397

Browse files
Refactor hook methods to share unified HookMethod base class
- Created abstract HookMethod base record with all shared properties - StaticHookMethod and InstanceHookMethod now inherit from HookMethod - Simplified HookRegisteredContext to work with single HookMethod type - Reduced EventReceiverOrchestrator hook processing from 15 lines to 3 - Simplified HookCollectionService hook registration logic - Hook event receivers now only need to handle HookMethod instead of both types Co-authored-by: Tom Longhurst <thomhurst@users.noreply.github.com>
1 parent dc3e186 commit f576397

6 files changed

Lines changed: 42 additions & 107 deletions

File tree

‎TUnit.Core/Contexts/HookRegisteredContext.cs‎

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@ namespace TUnit.Core;
77
/// </summary>
88
publicclassHookRegisteredContext
99
{
10-
privatereadonlyobject_hookMethod;
11-
privatereadonlystring_hookName;
1210
privateTimeSpan?_timeout;
1311

14-
publicStaticHookMethod?StaticHookMethod=>_hookMethodasStaticHookMethod;
15-
publicInstanceHookMethod?InstanceHookMethod=>_hookMethodasInstanceHookMethod;
16-
publicstringHookName=>_hookName;
12+
publicHookMethodHookMethod{get;}
13+
publicstringHookName=>HookMethod.Name;
1714

1815
/// <summary>
1916
/// Gets or sets the timeout for this hook
@@ -24,15 +21,8 @@ public TimeSpan? Timeout
2421
set=>_timeout=value;
2522
}
2623

27-
publicHookRegisteredContext(StaticHookMethodhookMethod)
24+
publicHookRegisteredContext(HookMethodhookMethod)
2825
{
29-
_hookMethod=hookMethod;
30-
_hookName=hookMethod.Name;
31-
}
32-
33-
publicHookRegisteredContext(InstanceHookMethodhookMethod)
34-
{
35-
_hookMethod=hookMethod;
36-
_hookName=hookMethod.Name;
26+
HookMethod=hookMethod;
3727
}
3828
}

‎TUnit.Core/Hooks/HookMethod.cs‎

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,37 @@
1-
namespaceTUnit.Core.Hooks;
1+
usingSystem.Diagnostics.CodeAnalysis;
2+
usingSystem.Reflection;
3+
usingTUnit.Core.Extensions;
4+
usingTUnit.Core.Interfaces;
25

3-
publicclassHookMethod
6+
namespaceTUnit.Core.Hooks;
7+
8+
#if !DEBUG
9+
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
10+
#endif
11+
publicabstractrecordHookMethod
412
{
5-
publicStaticHookMethod?StaticHookMethod{get;}
6-
publicInstanceHookMethod?InstanceHookMethod{get;}
13+
publicrequiredMethodMetadataMethodInfo{get;init;}
14+
15+
[field:AllowNull,MaybeNull]
16+
publicstringName=>field??=$"{ClassType.Name}.{MethodInfo.Name}({string.Join(", ",MethodInfo.Parameters.Select(x =>x.Name))})";
17+
18+
publicabstractTypeClassType{get;}
19+
publicvirtualAssembly?Assembly=>ClassType?.Assembly;
20+
21+
[field:AllowNull,MaybeNull]
22+
publicIEnumerable<Attribute>Attributes=>field??=MethodInfo.GetCustomAttributes();
23+
24+
publicTAttribute?GetAttribute<TAttribute>()whereTAttribute:Attribute=>Attributes.OfType<TAttribute>().FirstOrDefault();
725

8-
publicHookMethod(InstanceHookMethodinstanceHookMethod)
9-
{
10-
InstanceHookMethod=instanceHookMethod;
11-
}
26+
/// <summary>
27+
/// Gets the timeout for this hook method. This will be set during hook registration
28+
/// by the event receiver infrastructure, falling back to the default 5-minute timeout.
29+
/// </summary>
30+
publicTimeSpan?Timeout{get;internalset;}=TimeSpan.FromMinutes(5);
1231

13-
publicHookMethod(StaticHookMethodstaticHookMethod)
14-
{
15-
StaticHookMethod=staticHookMethod;
16-
}
32+
publicrequiredIHookExecutorHookExecutor{get;init;}
1733

18-
publicstaticimplicitoperatorHookMethod(InstanceHookMethodinstanceHookMethod)=>new(instanceHookMethod);
19-
publicstaticimplicitoperatorHookMethod(StaticHookMethodstaticHookMethod)=>new(staticHookMethod);
34+
publicrequiredintOrder{get;init;}
35+
36+
publicrequiredintRegistrationIndex{get;init;}
2037
}

‎TUnit.Core/Hooks/InstanceHookMethod.cs‎

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,10 @@ namespace TUnit.Core.Hooks;
88
#if !DEBUG
99
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
1010
#endif
11-
publicrecordInstanceHookMethod:IExecutableHook<TestContext>
11+
publicrecordInstanceHookMethod:HookMethod,IExecutableHook<TestContext>
1212
{
1313
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
14-
publicrequiredTypeClassType{get;init;}
15-
publicAssemblyAssembly=>ClassType.Assembly;
16-
publicrequiredMethodMetadataMethodInfo{get;init;}
17-
18-
[field:AllowNull,MaybeNull]
19-
publicstringName=>field??=$"{ClassType.Name}.{MethodInfo.Name}({string.Join(", ",MethodInfo.Parameters.Select(x =>x.Name))})";
20-
21-
[field:AllowNull,MaybeNull]publicIEnumerable<Attribute>Attributes=>field??=MethodInfo.GetCustomAttributes();
22-
23-
publicTAttribute?GetAttribute<TAttribute>()whereTAttribute:Attribute=>Attributes.OfType<TAttribute>().FirstOrDefault();
24-
25-
/// <summary>
26-
/// Gets or sets the timeout for this hook method. This will be set during hook registration
27-
/// by the event receiver infrastructure, falling back to the default 5-minute timeout.
28-
/// </summary>
29-
publicTimeSpan?Timeout{get;internalset;}=TimeSpan.FromMinutes(5);
30-
31-
publicrequiredIHookExecutorHookExecutor{get;init;}
32-
33-
publicrequiredintOrder{get;init;}
34-
35-
publicrequiredintRegistrationIndex{get;init;}
14+
publicoverrideTypeClassType{get;init;}
3615

3716
publicFunc<object,TestContext,CancellationToken,ValueTask>?Body{get;init;}
3817

‎TUnit.Core/Hooks/StaticHookMethod.cs‎

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,9 @@ public abstract record StaticHookMethod<T> : StaticHookMethod, IExecutableHook<T
1717
#if !DEBUG
1818
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
1919
#endif
20-
publicabstractrecordStaticHookMethod
20+
publicabstractrecordStaticHookMethod:HookMethod
2121
{
22-
publicrequiredMethodMetadataMethodInfo{get;init;}
23-
24-
[field:AllowNull,MaybeNull]
25-
publicstringName=>field??=$"{MethodInfo.Class.Type.Name}.{MethodInfo.Name}({string.Join(", ",MethodInfo.Parameters.Select(x =>x.Name))})";
26-
27-
publicTypeClassType=>MethodInfo.Class.Type;
28-
publicAssembly?Assembly=>ClassType?.Assembly;
29-
30-
[field:AllowNull,MaybeNull]
31-
publicIEnumerable<Attribute>Attributes=>field??=MethodInfo.GetCustomAttributes();
32-
33-
publicTAttribute?GetAttribute<TAttribute>()whereTAttribute:Attribute=>Attributes.OfType<TAttribute>().FirstOrDefault();
34-
35-
/// <summary>
36-
/// Gets the timeout for this hook method. This will be set during hook registration
37-
/// by the event receiver infrastructure, falling back to the default 5-minute timeout.
38-
/// </summary>
39-
publicTimeSpan?Timeout{get;internalset;}=TimeSpan.FromMinutes(5);
40-
41-
publicrequiredIHookExecutorHookExecutor{get;init;}
42-
43-
publicrequiredintOrder{get;init;}
44-
45-
publicrequiredintRegistrationIndex{get;init;}
22+
publicoverrideTypeClassType=>MethodInfo.Class.Type;
4623

4724
publicrequiredstringFilePath{get;init;}
4825

‎TUnit.Engine/Services/EventReceiverOrchestrator.cs‎

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -200,22 +200,7 @@ public async ValueTask InvokeTestDiscoveryEventReceiversAsync(TestContext contex
200200
publicasyncValueTaskInvokeHookRegistrationEventReceiversAsync(HookRegisteredContexthookContext,CancellationTokencancellationToken)
201201
{
202202
// Get event receivers from the hook method's attributes
203-
IEnumerable<Attribute>attributes;
204-
205-
if(hookContext.StaticHookMethod!=null)
206-
{
207-
attributes=hookContext.StaticHookMethod.Attributes;
208-
}
209-
elseif(hookContext.InstanceHookMethod!=null)
210-
{
211-
attributes=hookContext.InstanceHookMethod.Attributes;
212-
}
213-
else
214-
{
215-
return;// No hook method to process
216-
}
217-
218-
vareventReceivers=attributes
203+
vareventReceivers=hookContext.HookMethod.Attributes
219204
.OfType<IHookRegisteredEventReceiver>()
220205
.OrderBy(r =>r.Order)
221206
.ToList();

‎TUnit.Engine/Services/HookCollectionService.cs‎

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public HookCollectionService(EventReceiverOrchestrator eventReceiverOrchestrator
2828
_eventReceiverOrchestrator=eventReceiverOrchestrator;
2929
}
3030

31-
privateasyncTaskProcessHookRegistrationAsync(objecthookMethod,CancellationTokencancellationToken=default)
31+
privateasyncTaskProcessHookRegistrationAsync(HookMethodhookMethod,CancellationTokencancellationToken=default)
3232
{
3333
// Only process each hook once
3434
if(!_processedHooks.TryAdd(hookMethod,true))
@@ -38,20 +38,7 @@ private async Task ProcessHookRegistrationAsync(object hookMethod, CancellationT
3838

3939
try
4040
{
41-
HookRegisteredContextcontext;
42-
43-
if(hookMethodisStaticHookMethodstaticHook)
44-
{
45-
context=newHookRegisteredContext(staticHook);
46-
}
47-
elseif(hookMethodisInstanceHookMethodinstanceHook)
48-
{
49-
context=newHookRegisteredContext(instanceHook);
50-
}
51-
else
52-
{
53-
return;// Unknown hook type
54-
}
41+
varcontext=newHookRegisteredContext(hookMethod);
5542

5643
await_eventReceiverOrchestrator.InvokeHookRegistrationEventReceiversAsync(context,cancellationToken);
5744
}

0 commit comments

Comments
 (0)