Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
reorder fields to match guidelines
  • Loading branch information
beervoley committed May 31, 2025
commit 02029085aa8dfbea4547b3d889b56b66801e5a6f
25 changes: 14 additions & 11 deletions src/ComServerHelpers/BaseClassFactory.cs
Original file line number Diff line number Diff line change
@@ -13,17 +13,7 @@ namespace ComServerHelpers;
[SupportedOSPlatform("windows6.0.6000")]
public abstract class BaseClassFactory
{
/// <summary>
/// Creates an instance of the object.
/// </summary>
/// <returns>An instance of the object.</returns>
protected internal abstract object CreateInstance();

/// <summary>
/// Occurs when a new instance is created.
/// </summary>
public event EventHandler<InstanceCreatedEventArgs>? InstanceCreated;

// Properties (special values)
/// <summary>
/// Gets the <c>CLSID</c>.
/// </summary>
@@ -40,6 +30,19 @@ protected internal abstract Guid Iid
get;
}

// Events
/// <summary>
/// Occurs when a new instance is created.
/// </summary>
public event EventHandler<InstanceCreatedEventArgs>? InstanceCreated;

// Other members (methods)
/// <summary>
/// Creates an instance of the object.
/// </summary>
/// <returns>An instance of the object.</returns>
protected internal abstract object CreateInstance();

/// <summary>
/// Raises the <see cref="InstanceCreated"/> event.
/// </summary>
59 changes: 30 additions & 29 deletions src/ComServerHelpers/ComServer.cs
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ namespace ComServerHelpers;
[SupportedOSPlatform("windows6.0.6000")]
public sealed class ComServer : IDisposable
{
// State
/// <summary>
/// Map of class factories and the registration cookie from the CLSID that the factory creates.
/// </summary>
@@ -48,6 +49,7 @@ public sealed class ComServer : IDisposable
/// </summary>
private TaskCompletionSource<object>? firstInstanceCreated;

// Constructor
/// <summary>
/// Initializes a new instance of the <see cref="ComServer"/> class.
/// </summary>
@@ -56,6 +58,24 @@ public unsafe ComServer()
Utils.SetDefaultGlobalOptions();
}

// Properties (special values)
/// <summary>
/// Gets a value indicating whether the server is running.
/// </summary>
public bool IsRunning { get; private set; }

/// <summary>
/// Gets a value indicating whether the instance is disposed.
/// </summary>
public bool IsDisposed { get; private set; }

// Events
/// <summary>
/// Occurs when the server creates an object.
/// </summary>
public event EventHandler<InstanceCreatedEventArgs>? InstanceCreated;

// Other members (methods)
/// <summary>
/// Register a class factory with the server.
/// </summary>
@@ -134,22 +154,6 @@ public unsafe bool UnregisterClassFactory(Guid clsid)
return true;
}

private void Factory_InstanceCreated(object? sender, InstanceCreatedEventArgs e)
{
if (IsDisposed)
{
return;
}

InstanceCreated?.Invoke(this, e);
firstInstanceCreated?.TrySetResult(e.Instance);
}

/// <summary>
/// Gets a value indicating whether the server is running.
/// </summary>
public bool IsRunning { get; private set; }

/// <summary>
/// Starts the server.
/// </summary>
@@ -202,15 +206,6 @@ public void Stop()
return await local.Task.ConfigureAwait(false);
}

/// <summary>
/// Gets a value indicating whether the instance is disposed.
/// </summary>
public bool IsDisposed
{
get;
private set;
}

/// <summary>
/// Force the server to stop and release all resources.
/// </summary>
@@ -236,8 +231,14 @@ public void Dispose()
}
}

/// <summary>
/// Occurs when the server creates an object.
/// </summary>
public event EventHandler<InstanceCreatedEventArgs>? InstanceCreated;
private void Factory_InstanceCreated(object? sender, InstanceCreatedEventArgs e)
{
if (IsDisposed)
{
return;
}

InstanceCreated?.Invoke(this, e);
firstInstanceCreated?.TrySetResult(e.Instance);
}
}
3 changes: 3 additions & 0 deletions src/ComServerHelpers/DelegateActivationFactory.cs
Original file line number Diff line number Diff line change
@@ -15,11 +15,14 @@ namespace ComServerHelpers;
[SupportedOSPlatform("windows8.0")]
public sealed class DelegateActivationFactory<T>(Func<T> factory) : BaseActivationFactory where T : class
{
// State
private readonly Func<T> factory = factory;

// Properties (special values)
/// <inheritdoc/>
public override string ActivatableClassId => typeof(T).FullName ?? throw new InvalidOperationException($"Unable to get activation class ID for type {typeof(T)}");

// Other members (methods)
/// <inheritdoc/>
public override object ActivateInstance()
{
3 changes: 3 additions & 0 deletions src/ComServerHelpers/DelegateClassFactory.cs
Original file line number Diff line number Diff line change
@@ -16,14 +16,17 @@ namespace ComServerHelpers;
[SupportedOSPlatform("windows6.0.6000")]
public sealed class DelegateClassFactory<T, TInterface>(Func<T> factory) : BaseClassFactory where T : class, TInterface
{
// State
private readonly Func<T> factory = factory;

// Properties (special values)
/// <inheritdoc/>
protected internal override Guid Clsid => typeof(T).GUID;

/// <inheritdoc/>
protected internal override Guid Iid => typeof(TInterface).GUID;

// Other members (methods)
/// <inheritdoc/>
protected internal override object CreateInstance()
{
105 changes: 55 additions & 50 deletions src/ComServerHelpers/WinRtServer.cs
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ namespace ComServerHelpers;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1724", Justification = "No better idea")]
public sealed class WinRtServer : IDisposable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely let's not use "WinRt" as a type name. Should at the very least be "WinRT".
Ideally this should eventually be "WindowsRuntimeServer" in 3.0. We can do that now or later,

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaving typenames/namespace changing to be very last changes.

{
// State
/// <summary>
/// Mapping of Activatable Class IDs to activation factories and their <see cref="ComWrappers"/> implementation.
/// </summary>
@@ -56,6 +57,7 @@ public sealed class WinRtServer : IDisposable

private RO_REGISTRATION_COOKIE registrationCookie = (RO_REGISTRATION_COOKIE)0;

// Constructor
/// <summary>
/// Initializes a new instance of the <see cref="WinRtServer"/> class.
/// </summary>
@@ -67,17 +69,28 @@ public unsafe WinRtServer()
Utils.SetDefaultGlobalOptions();
}

private void Factory_InstanceCreated(object? sender, InstanceCreatedEventArgs e)
// Properties (special values)
/// <summary>
/// Gets a value indicating whether the instance is disposed.
/// </summary>
public bool IsDisposed
{
if (IsDisposed)
{
return;
}

InstanceCreated?.Invoke(this, e);
firstInstanceCreated?.TrySetResult(e.Instance);
get;
private set;
}

/// <summary>
/// Gets a value indicating whether the server is running.
/// </summary>
public bool IsRunning => registrationCookie != 0;

// Events
/// <summary>
/// Occurs when the server creates an object.
/// </summary>
public event EventHandler<InstanceCreatedEventArgs>? InstanceCreated;

// Other members (methods)
/// <summary>
/// Register an activation factory with the server.
/// </summary>
@@ -125,44 +138,6 @@ public bool UnregisterActivationFactory(BaseActivationFactory factory)
return factories.Remove(factory.ActivatableClassId);
}

private unsafe HRESULT ActivationFactoryCallback(HSTRING activatableClassId, IActivationFactory** factory)
{
if (activatableClassId == HSTRING.Null || factory is null)
{
return HRESULT.E_INVALIDARG;
}

if (!factories.TryGetValue(activatableClassId.AsString(), out var managedFactory))
{
factory = null;
return HRESULT.E_NOINTERFACE;
}

var unknown = Utils.StrategyBasedComWrappers.GetOrCreateComInterfaceForObject(new BaseActivationFactoryWrapper(managedFactory.Factory, managedFactory.Wrapper), CreateComInterfaceFlags.None);
var hr = (HRESULT)Marshal.QueryInterface(unknown, in global::Windows.Win32.System.WinRT.IActivationFactory.IID_Guid, out nint ppv);
*factory = (IActivationFactory*)ppv;
if (unknown != 0)
{
Marshal.Release(unknown);
}

return hr;
}

/// <summary>
/// Gets a value indicating whether the instance is disposed.
/// </summary>
public bool IsDisposed
{
get;
private set;
}

/// <summary>
/// Gets a value indicating whether the server is running.
/// </summary>
public bool IsRunning => registrationCookie != 0;

/// <summary>
/// Starts the server.
/// </summary>
@@ -271,8 +246,38 @@ public void Dispose()
}
}

/// <summary>
/// Occurs when the server creates an object.
/// </summary>
public event EventHandler<InstanceCreatedEventArgs>? InstanceCreated;
private unsafe HRESULT ActivationFactoryCallback(HSTRING activatableClassId, IActivationFactory** factory)
{
if (activatableClassId == HSTRING.Null || factory is null)
{
return HRESULT.E_INVALIDARG;
}

if (!factories.TryGetValue(activatableClassId.AsString(), out var managedFactory))
{
factory = null;
return HRESULT.E_NOINTERFACE;
}

var unknown = Utils.StrategyBasedComWrappers.GetOrCreateComInterfaceForObject(new BaseActivationFactoryWrapper(managedFactory.Factory, managedFactory.Wrapper), CreateComInterfaceFlags.None);
var hr = (HRESULT)Marshal.QueryInterface(unknown, in global::Windows.Win32.System.WinRT.IActivationFactory.IID_Guid, out nint ppv);
*factory = (IActivationFactory*)ppv;
if (unknown != 0)
{
Marshal.Release(unknown);
}

return hr;
}

private void Factory_InstanceCreated(object? sender, InstanceCreatedEventArgs e)
{
if (IsDisposed)
{
return;
}

InstanceCreated?.Invoke(this, e);
firstInstanceCreated?.TrySetResult(e.Instance);
}
}
Loading
Oops, something went wrong.