11using Microsoft . Extensions . Logging ;
22using System . Reflection ;
3+ using System . Runtime . CompilerServices ;
34using System . Runtime . ExceptionServices ;
45
56namespace Bunit . Rendering ;
67
78/// <summary>
89/// Represents a bUnit <see cref="ITestRenderer"/> used to render Blazor components and fragments during bUnit tests.
910/// </summary>
10- [ SuppressMessage ( "Major Code Smell" , "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields" , Justification = "Blazors internal API has been stable for a while now." ) ]
1111public class TestRenderer : Renderer , ITestRenderer
1212{
13+ #if NET8_0_OR_GREATER
14+ [ UnsafeAccessor ( UnsafeAccessorKind . Field , Name = "_isBatchInProgress" ) ]
15+ extern static ref bool GetIsBatchInProgressField ( Renderer renderer ) ;
16+
17+ [ UnsafeAccessor ( UnsafeAccessorKind . Method , Name = "SetDirectParameters" ) ]
18+ extern static void CallSetDirectParameters ( ComponentState componentState , ParameterView parameters ) ;
19+ #else
1320 private static readonly Type RendererType = typeof ( Renderer ) ;
14- private static readonly FieldInfo IsBatchInProgressField = RendererType . GetField ( "_isBatchInProgress" , BindingFlags . Instance | BindingFlags . NonPublic ) ! ;
15- #if ! NET8_0_OR_GREATER
1621 private static readonly MethodInfo GetRequiredComponentStateMethod = RendererType . GetMethod ( "GetRequiredComponentState" , BindingFlags . Instance | BindingFlags . NonPublic ) ! ;
22+ private static readonly FieldInfo IsBatchInProgressField = RendererType . GetField ( "_isBatchInProgress" , BindingFlags . Instance | BindingFlags . NonPublic ) ! ;
1723#endif
1824
1925 private readonly object renderTreeUpdateLock = new ( ) ;
@@ -28,9 +34,23 @@ public class TestRenderer : Renderer, ITestRenderer
2834 private bool IsBatchInProgress
2935 {
3036#pragma warning disable S1144 // Unused private types or members should be removed
31- get => ( bool ) ( IsBatchInProgressField . GetValue ( this ) ?? false ) ;
37+ get
38+ {
39+ #if NET8_0_OR_GREATER
40+ return GetIsBatchInProgressField ( this ) ;
41+ #else
42+ return ( bool ) ( IsBatchInProgressField . GetValue ( this ) ?? false ) ;
43+ #endif
44+ }
3245#pragma warning restore S1144 // Unused private types or members should be removed
33- set => IsBatchInProgressField . SetValue ( this , value ) ;
46+ set
47+ {
48+ #if NET8_0_OR_GREATER
49+ GetIsBatchInProgressField ( this ) = value;
50+ #else
51+ IsBatchInProgressField . SetValue ( this , value ) ;
52+ #endif
53+ }
3454 }
3555
3656 /// <inheritdoc/>
@@ -217,15 +237,7 @@ internal Task SetDirectParametersAsync(IRenderedFragmentBase renderedComponent,
217237 try
218238 {
219239 IsBatchInProgress = true ;
220-
221- #if NET8_0_OR_GREATER
222- var setDirectParametersMethod = typeof ( ComponentState ) . GetMethod ( "SetDirectParameters" , BindingFlags . NonPublic | BindingFlags . Instance ) ! ;
223- var componentState = GetComponentState ( renderedComponent . ComponentId ) ;
224- #else
225- var componentState = GetRequiredComponentStateMethod . Invoke ( this , new object [ ] { renderedComponent . ComponentId } ) ! ;
226- var setDirectParametersMethod = componentState . GetType ( ) . GetMethod ( "SetDirectParameters" , BindingFlags . Public | BindingFlags . Instance ) ! ;
227- #endif
228- setDirectParametersMethod . Invoke ( componentState , new object [ ] { parameters } ) ;
240+ SetDirectParametersViaComponentState ( this , renderedComponent . ComponentId , parameters ) ;
229241 }
230242 catch ( TargetInvocationException ex ) when ( ex . InnerException is not null )
231243 {
@@ -247,6 +259,21 @@ internal Task SetDirectParametersAsync(IRenderedFragmentBase renderedComponent,
247259 AssertNoUnhandledExceptions ( ) ;
248260
249261 return result ;
262+
263+ #if NET8_0_OR_GREATER
264+ static void SetDirectParametersViaComponentState ( TestRenderer renderer , int componentId , in ParameterView parameters )
265+ {
266+ var componentState = renderer . GetComponentState ( componentId ) ;
267+ CallSetDirectParameters ( componentState , parameters ) ;
268+ }
269+ #else
270+ static void SetDirectParametersViaComponentState ( TestRenderer renderer , int componentId , in ParameterView parameters )
271+ {
272+ var componentState = GetRequiredComponentStateMethod . Invoke ( renderer , new object [ ] { componentId } ) ! ;
273+ var setDirectParametersMethod = componentState . GetType ( ) . GetMethod ( "SetDirectParameters" , BindingFlags . Public | BindingFlags . Instance ) ! ;
274+ setDirectParametersMethod . Invoke ( componentState , new object [ ] { parameters } ) ;
275+ }
276+ #endif
250277 }
251278
252279 /// <inheritdoc/>
0 commit comments