Skip to content

Expose interop manipulation of SafeHandle #46830

@AaronRobinsonMSFT

Description

@AaronRobinsonMSFT

Background and Motivation

The SafeHandle type was designed around an assumption that the runtime could manage all aspects of its lifetime. The source generation proposal pushed this responsible onto a third party tool (i.e. Roslyn source generator). In order to better support that scenario, the following APIs are proposed to help with SafeHandle manipulation.

Proposed API

Update guidance here to indicate derived types would need a public default constructor. This proposal would include ensuring all SafeHandle implementations provided by .NET follow this guidance.

Expose SetHandle as a public API so source generators may call it.

See #45633 (comment).

Usage Examples

Usage example would the ability to call SetHandle and instantiate any type derived from SafeHandle so they can be used from a source generator.

Alternative Designs

Expose static functions for SafeHandle manipulation.

namespace System.Runtime.InteropServices
{
    public static class Marshal
    {
+        /// <summary>
+        /// Create an instance of the given <typeparamref name="TSafeHandle"/>.
+        /// </summary>
+        /// <typeparam name="TSafeHandle">Type of the SafeHandle</typeparam>
+        /// <returns>New instance of <typeparamref name="TSafeHandle"/></returns>
+        /// <remarks>
+        /// The <typeparamref name="TSafeHandle"/> must be non-abstract and have a parameterless constructor.
+        /// </remarks>
+        public static TSafeHandle CreateSafeHandle<
+                      [DynamicallyAccessedMembers(
+                              DynamicallyAccessedMemberTypes.PublicParameterlessConstructor
+                              | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
+                       TSafeHandle>() where TSafeHandle : SafeHandle;

+        /// <summary>
+        /// Sets the handle of <paramref name="safeHandle"/> to the specified <paramref name="handle"/>.
+        /// </summary>
+        /// <param name="safeHandle"><see cref="SafeHandle"/> instance to update</param>
+        /// <param name="handle">Pre-existing handle</param>
+        public static void SetHandle(SafeHandle safeHandle, IntPtr handle);
    }
}

Risks

Low. These APIs expose internal lifetime operations that users have often wanted to hide. This is however mitigated by the fact that using reflection these "hidden" APIs can be used regardless.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-System.Runtime.InteropServicescode-analyzerMarks an issue that suggests a Roslyn analyzercode-fixerMarks an issue that suggests a Roslyn code fixerhelp wanted[up-for-grabs] Good issue for external contributors

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions