|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace System;
/// <summary>
/// Interface for accessing internals from tests.
/// </summary>
/// <remarks>
/// <para>
/// A non generic representation of the accessor functionality is needed to
/// allow dynamically creating arbitrary <see cref="TestAccessor{T}"/> from
/// helper methods.
/// </para>
/// </remarks>
public interface ITestAccessor
{
/// <summary>
/// Gets a dynamic accessor to internals on the test object.
/// </summary>
/// <remarks>
/// <para>
/// This does not work for ref structs as they are not yet accessible via reflection.
/// See https://github.com/dotnet/runtime/issues/10057.
/// </para>
/// </remarks>
dynamic Dynamic { get; }
/// <summary>
/// Creates a delegate for the given non-public method.
/// </summary>
/// <param name="methodName">
/// The method name. If null, uses the name of the delegate for the method.
/// </param>
/// <remarks>
/// <para>
/// This provides a way to access methods that take ref structs.
/// </para>
/// </remarks>
/// <example>
/// <![CDATA[
/// // For ref structs you have to define a delegate as ref struct types
/// // cannot be used as generic arguments (e.g. to Func/Span)
///
/// private delegate int GetDirectoryNameOffset(ReadOnlySpan<char> path);
///
/// public int InternalGetDirectoryNameOffset(ReadOnlySpan<char> path)
/// {
/// var accessor = typeof(System.IO.Path).TestAccessor();
/// return accessor.CreateDelegate<GetDirectoryNameOffset>()(@"C:\Foo");
/// }
///
/// // Without ref structs you can just use Func/Action
/// var accessor = typeof(Color).TestAccessor();
/// bool result = accessor.CreateDelegate<Func<KnownColor, bool>>("IsKnownColorSystem")(KnownColor.Window);
/// ]]>
/// </example>
TDelegate CreateDelegate<TDelegate>(string? methodName = null)
where TDelegate : Delegate;
}
|