Skip to content

GeneratedComInterface/Class needs a way to register a factory method #111616

@m-celikba

Description

@m-celikba

In built in COM we had ExtensibleClassFactory.RegisterObjectCreationCallback where we could register a factory method (often in native code)

[ComImport, Guid(<guid1>)]
public interface IMyInterface
{
   void DoStuff();
}

[ComImport, Guid(<guid2>)]
public class MyClassHelper : IMyInterface
{
    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
    public virtual extern void DoStuff();
}

[Guid(<guid2>)]
public class MyClass : MyClassHelper 
{
    static MyClass() 
    {
        ExtensibleClassFactory.RegisterObjectCreationCallback(new ObjectCreationDelegate(CreateComInstanceDelegate));
    }
    private static IntPtr CreateComInstanceDelegate(IntPtr aggr) 
    {
        return NativeMethods.CreateComInstance(typeof(MyClass).Guid);
    }
}

// usage
var inst = new MyClass();
inst.DoStuff();

in source generated COM I can do:

[GeneratedComInterface, Guid(<guid1>)]
public interface IMyInterface
{
   void DoStuff();
}

// usage
var ptr = NativeMethods.CreateComInstance(typeof(MyClass).Guid);
var inst = ComInterfaceMarshaller<IMyInterface>.ConvertToManaged(ptr);
inst.DoStuff();

which is not as straight forward as before.
Instead I can use the decorator pattern:

[GeneratedComClass, Guid(<guid2>)]
public class MyClass : IMyInterface 
{
    private IMyInterface _inner;
    public MyClass()
    {
        var ptr = NativeMethods.CreateComInstance(typeof(MyClass).Guid);
        _inner = ComInterfaceMarshaller<IMyInterface>.ConvertToManaged(ptr);
    }

    public void DoStuff() => _inner.DoStuff();
}

// usage
var inst = new MyClass();
inst.DoStuff();

I know I can probably write a source generator that does exactly that but it will be great if the default tooling could do that for us.
something like:

[GeneratedComClassWrapper(typeof(IMyInterface)), Guid(<guid2>)]
public class MyClass 
{
    static MyClass() 
    {
        RegisterObjectCreationCallback(static _ => NativeMethods.CreateComInstance(typeof(MyClass).Guid));
    }
}

// usage
var inst = new MyClass();
inst.DoStuff();

This would help migrating dotnet framework code that make heavy use of builtin COM interop.

EDIT: fixed declaration of _inner

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions