}
}
+ /// <summary>
+ /// Creates a new read-only span over this immutable array.
+ /// </summary>
+ /// <returns>The read-only span representation of this immutable array.</returns>
public ReadOnlySpan<T> AsSpan() => new ReadOnlySpan<T>(array);
+ /// <summary>
+ /// Creates a new read-only memory region over this immutable array.
+ /// </summary>
+ /// <returns>The read-only memory representation of this immutable array.</returns>
public ReadOnlyMemory<T> AsMemory() => new ReadOnlyMemory<T>(array);
/// <summary>
/// Items should not be added or removed from the <see cref="List{T}"/> while the <see cref="Span{T}"/> is in use.
/// </summary>
/// <param name="list">The list to get the data view over.</param>
+ /// <typeparam name="T">The type of the elements in the list.</typeparam>
public static Span<T> AsSpan<T>(List<T>? list)
=> list is null ? default : new Span<T>(list._items, 0, list._size);
/// </summary>
/// <param name="dictionary">The dictionary to get the ref to <typeparamref name="TValue"/> from.</param>
/// <param name="key">The key used for lookup.</param>
+ /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
+ /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
/// <remarks>
/// Items should not be added or removed from the <see cref="Dictionary{TKey, TValue}"/> while the ref <typeparamref name="TValue"/> is in use.
/// The ref null can be detected using System.Runtime.CompilerServices.Unsafe.IsNullRef
/// <param name="dictionary">The dictionary to get the ref to <typeparamref name="TValue"/> from.</param>
/// <param name="key">The key used for lookup.</param>
/// <param name="exists">Whether or not a new entry for the given key was added to the dictionary.</param>
+ /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
+ /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
/// <remarks>Items should not be added to or removed from the <see cref="Dictionary{TKey, TValue}"/> while the ref <typeparamref name="TValue"/> is in use.</remarks>
public static ref TValue? GetValueRefOrAddDefault<TKey, TValue>(Dictionary<TKey, TValue> dictionary, TKey key, out bool exists) where TKey : notnull
=> ref Dictionary<TKey, TValue>.CollectionsMarshalHelper.GetValueRefOrAddDefault(dictionary, key, out exists);
/// </summary>
/// <param name="list">The list to set the count of.</param>
/// <param name="count">The value to set the list's count to.</param>
+ /// <typeparam name="T">The type of the elements in the list.</typeparam>
/// <exception cref="NullReferenceException">
/// <paramref name="list"/> is <see langword="null"/>.
/// </exception>
public sealed class ComExposedClassAttribute<T> : Attribute, IComExposedDetails
where T : IComExposedClass
{
- /// <inheritdoc />
+ /// <inheritdoc cref="IComExposedDetails.GetComInterfaceEntries(out int)" />
public unsafe ComWrappers.ComInterfaceEntry* GetComInterfaceEntries(out int count) => T.GetComInterfaceEntries(out count);
}
}
/// This marshaller will always pass the <see cref="CreateObjectFlags.Unwrap"/> flag
/// to <see cref="ComWrappers.GetOrCreateObjectForComInstance(IntPtr, CreateObjectFlags)"/>.
/// </remarks>
+ /// <typeparam name="T">The managed type that represents a COM interface type</typeparam>
[UnsupportedOSPlatform("android")]
[UnsupportedOSPlatform("browser")]
[UnsupportedOSPlatform("ios")]
[CLSCompliant(false)]
public unsafe interface IIUnknownCacheStrategy
{
+ /// <summary>
+ /// A structure that contains information about a COM interface and its virtual method table.
+ /// </summary>
public readonly struct TableInfo
{
+ /// <summary>
+ /// The <c>this</c> pointer of the unmanaged interface.
+ /// </summary>
public void* ThisPtr { get; init; }
+ /// <summary>
+ /// A pointer to the virtual method table for this unmanaged interface.
+ /// </summary>
public void** Table { get; init; }
+ /// <summary>
+ /// The managed type that provides a managed projection of the unmanaged interface.
+ /// </summary>
public RuntimeTypeHandle ManagedType { get; init; }
}
/// </summary>
/// <param name="instancePtr">A pointer representing the unmanaged instance.</param>
/// <param name="iid">The IID (Interface ID) to query for.</param>
- /// <param name="ppObj">The resulting interface</param>
- /// <returns>Returns an HRESULT represents the success of the operation</returns>
+ /// <param name="ppObj">The resulting interface.</param>
+ /// <returns>Returns an HRESULT represents the success of the operation.</returns>
/// <seealso cref="Marshal.QueryInterface(nint, ref Guid, out nint)"/>
public int QueryInterface(void* instancePtr, in Guid iid, out void* ppObj);
namespace System.Runtime.InteropServices.Marshalling
{
+ /// <summary>
+ /// A <see cref="ComWrappers"/>-based type that uses customizable strategy objects to implement COM object wrappers and managed object wrappers exposed to COM.
+ /// </summary>
[CLSCompliant(false)]
public class StrategyBasedComWrappers : ComWrappers
{
internal static StrategyBasedComWrappers DefaultMarshallingInstance { get; } = new();
+ /// <summary>
+ /// The default strategy to discover interface details about COM interfaces.
+ /// </summary>
+ /// <remarks>
+ /// This strategy can discover interfaces and classes that use source-generated COM interop that use the <see cref="GeneratedComInterfaceAttribute"/> and <see cref="GeneratedComClassAttribute"/> attributes.
+ /// This strategy looks for an <see cref="IUnknownDerivedAttribute{T, TImpl}"/> or <see cref="ComExposedClassAttribute{T}"/> attribute on the type of the provided object to discover COM type information.
+ /// </remarks>
public static IIUnknownInterfaceDetailsStrategy DefaultIUnknownInterfaceDetailsStrategy { get; } = Marshalling.DefaultIUnknownInterfaceDetailsStrategy.Instance;
+ /// <summary>
+ /// The default strategy to use for calling <c>IUnknown</c> methods.
+ /// </summary>
+ /// <remarks>
+ /// This strategy assumes that all provided COM objects are free threaded and that calls to <c>IUnknown</c> methods can be made from any thread.
+ /// </remarks>
public static IIUnknownStrategy DefaultIUnknownStrategy { get; } = FreeThreadedStrategy.Instance;
+ /// <summary>
+ /// The default strategy to use for caching COM objects.
+ /// </summary>
+ /// <returns>The default strategy caches the interface pointers per interface no matter what thread they were initially retrieved on.</returns>
protected static IIUnknownCacheStrategy CreateDefaultCacheStrategy() => new DefaultCaching();
+ /// <summary>
+ /// Get or create the interface details strategy for a new COM object wrapper.
+ /// </summary>
+ /// <returns>The interface details strategy to use for the new COM object.</returns>
protected virtual IIUnknownInterfaceDetailsStrategy GetOrCreateInterfaceDetailsStrategy()
{
if (OperatingSystem.IsWindows() && RuntimeFeature.IsDynamicCodeSupported && ComObject.BuiltInComSupported && ComObject.ComImportInteropEnabled)
}
}
+ /// <summary>
+ /// Get or create the IUnknown strategy for a new COM object wrapper.
+ /// </summary>
+ /// <returns>The IUnknown strategy to use for the new COM object.</returns>
protected virtual IIUnknownStrategy GetOrCreateIUnknownStrategy() => DefaultIUnknownStrategy;
+ /// <summary>
+ /// Create the caching strategy for a new COM object wrapper.
+ /// </summary>
+ /// <returns>The caching strategy to use for the new COM object.</returns>
protected virtual IIUnknownCacheStrategy CreateCacheStrategy() => CreateDefaultCacheStrategy();
+ /// <inheritdoc cref="ComWrappers.ComputeVtables" />
protected sealed override unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count)
{
if (obj.GetType().GetCustomAttribute(typeof(ComExposedClassAttribute<>)) is IComExposedDetails details)
return null;
}
+ /// <inheritdoc cref="ComWrappers.CreateObject" />
protected sealed override unsafe object CreateObject(nint externalComObject, CreateObjectFlags flags)
{
if (flags.HasFlag(CreateObjectFlags.TrackerObject)
return rcw;
}
+ /// <inheritdoc cref="ComWrappers.ReleaseObjects" />
protected sealed override void ReleaseObjects(IEnumerable objects)
{
throw new NotImplementedException();
/// This marshaller will always pass the <see cref="CreateObjectFlags.Unwrap"/> and <see cref="CreateObjectFlags.UniqueInstance"/> flags
/// to <see cref="ComWrappers.GetOrCreateObjectForComInstance(IntPtr, CreateObjectFlags)"/>.
/// </remarks>
+ /// <typeparam name="T">The managed type that represents a COM interface type</typeparam>
[UnsupportedOSPlatform("android")]
[UnsupportedOSPlatform("browser")]
[UnsupportedOSPlatform("ios")]