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); // Instance
Risks
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.
Background and motivation
A current API exists for taking in an
IntPtrto anIUnknownand 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 callingComWrappers.GetOrRegisterObjectForComInstance()orComWrappers.GetOrCreateObjectForComInstance().API Proposal
The proposal here is to reuse the
TryGetObject()pattern, but for a nativeIUnknownas opposed to check if theIUnknownis 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
Alternative Designs
Convert to instance method
Follow the existing pattern and create a "Try" version
Risks
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
GetOrCreateObjectForComInstanceorGetOrRegisterObjectForComInstance. This can be mitigated if the user'sComWrappersimplementation ensures that it would always create a wrapper for anIUnknowninstance based solely on the state of thatIUnknown, but that is a hard requirement to enforce.