Для справки: с помощью здесь и github-проблема нашла решение:
Наличие двух проектов:
- ClassLibrary1 для вызова из VBA
- ClassLibrary2для использования внутри ClassLibrary1 (без предоставления чего-либо для VBA)
В ClassLibrary1 у нас есть статический класс UnmanagedExport:
static class UnmanagedExport
{
static UnmanagedExport()
=> AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
=> Assembly.LoadFrom($@"{new FileInfo(args.RequestingAssembly.Location).DirectoryName}\{args.Name.Split(',')[0]}.dll");
[DllExport]
[return: MarshalAs(UnmanagedType.IDispatch)]
static object CreateBroker()
=> new Class1();
}
CreateBroker () создает экземпляр Class1 (который должен быть посредником между VBA и ClassLibrary2).ClassLibrary1.Class1:
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Class1
{
public void DoNothingOnClass2Typed()
=> new Class2().DoNothing();
public void CreateClass2aFromClass2Typed()
=> new Class2().CreateClass2a();
}
Class2 (и Class2a) оба находятся в ClassLibrary2 (на который ссылается ClassLibrary1):
namespace ClassLibrary2
{
public class Class2
{
public void DoNothing()
{
return;
}
public void CreateClass2a()
{
var class2a = new Class2a();
}
}
}
В VBA это называется:
Declare Function CreateBroker Lib "C:\source\repos\DllExportTest\ClassLibrary1\bin\Debug\ClassLibrary1.dll" () As Object
Public Sub RunTest()
Dim class1 As Object
Set class1 = CreateBroker()
class1.DoNothingOnClass2Typed
class1.CreateClass2aFromClass2Typed
Set class1 = Nothing
End Sub
Работает как шарм!
Примечание: ClassLibrary2 также может быть .NET Standard dll, поэтому решение совместимо также с .NET Core.