-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
Background and motivation
A current API exists for taking in an IntPtr to an IUnknown and checking if it is a CCW (COM Callable Wrapper). Adding a symmetrical API for checking if there is an existing wrapper for an RCW (Runtime Callable Wrapper) is also potentially interesting since it could be the case that users may want to perform a non-exception throwing check prior to calling ComWrappers.GetOrRegisterObjectForComInstance() or ComWrappers.GetOrCreateObjectForComInstance().
API Proposal
The proposal here is to reuse the TryGetObject() pattern, but for a native IUnknown as opposed to check if the IUnknown is an existing CCW (wrapper of a managed object).
namespace System.Runtime.InteropServices;
public abstract class ComWrappers
{
+ public static bool TryGetObject(IntPtr externalComObject, ComWrappers comWrappers, out object? wrapper);
}API Usage
public static MyCallbackApi(IntPtr unknown)
{
if (!ComWrappers.TryGetObject(unknown, g_comWrapper, out object? existingWrapper))
{
//
// Do some inspection of the unknown and/or perform actions that need to be done
// prior to actually attempting the creation.
//
existingWrapper = g_comWrapper.GetOrCreateObjectForComInstance(unknown, CreateObjectFlags.None);
}
}Alternative Designs
Convert to instance method
public bool TryGetObject(IntPtr externalComObject, out object? wrapper);Follow the existing pattern and create a "Try" version
public bool TryGetOrCreateObjectForComInstance(IntPtr externalComObject, CreateObjectFlags flags, [NotNullWhen(true)] out object? wrapper); // InstanceRisks
This is for a niche WinRT scenario. It has no other obvious uses at present. It does however create a symmetrical API for both CCWs and RCWs.
The API has a trivial implementation, but does introduce an inherent race condition around what is in essence a concurrent dictionary (RCW cache). The "try" operation is checking for state that might be addressed by another thread calling the GetOrCreateObjectForComInstance or GetOrRegisterObjectForComInstance. This can be mitigated if the user's ComWrappers implementation ensures that it would always create a wrapper for an IUnknown instance based solely on the state of that IUnknown, but that is a hard requirement to enforce.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status