解析 COM 互操作类型时出现 SimpleInjector ActivatorException
SimpleInjector ActivatorException when resolving COM interop type
当试图从我的 Simple Injector 容器解析类型时,它抛出一个 ActivatorException
说我的类型没有注册,虽然我很确定它已经注册了。
ThisAddin.cs
private void ThisAddIn_Startup(object sender, EventArgs e)
{
var container = new Container();
container.RegisterSingleton<Microsoft.Office.Interop.Excel.Application>(() => this.GetHostItem<Microsoft.Office.Interop.Excel.Application>(
typeof(Microsoft.Office.Interop.Excel.Application), "Application"));
var application = container.GetInstance<IApplicationAdapter>();
}
在另一个大会中,在这种情况下 ExcelInterface
。
ApplicationAdapter.cs
internal class ApplicationAdapter : IApplicationAdapter
{
public Application(Microsoft.Office.Interop.Excel.Application excelApplication)
{
}
}
我ApplicationAdapter.cs
public interface IApplicationAdapter
{
}
但是在解决 Excel.Application
时,我得到的异常是:
所以尝试调试这个我认为它实际上没有被正确注册,但是当检查容器中添加的注册时我可以看到 Excel.Application
已经被添加:
我还检查并 100% 确定这两个 类 引用的是同一个 Excel.Application
程序集。
最后我将 Excel.Application
实例添加到容器中,但由于这是 __COMObject
我无法将其注册为 Excel.Application
.
我完全不知道为什么 Simple Injector 无法正确解析接口。
我不确定为什么会这样。我可以确认在您的示例中尝试注册时发生异常。
对于你正在尝试做的事情,我同意史蒂文的评论,哎呀!!在应用程序对象上创建您自己的、可能的多个抽象应该是可行的方法。
不过,只需稍作改动即可实现您想要的效果。您可以像这样注册一个 IApplicationProvider
,而不是注册应用程序对象本身(它会因某些奇怪的原因而抛出):
internal interface IApplicationProvider
{
Excel.Application CurrentApplication { get; }
}
class ApplicationProvider : IApplicationProvider
{
public ApplicationProvider(Excel.Application application)
{
this.CurrentApplication = application;
}
// c# 6 syntax
public Excel.Application CurrentApplication { get; }
}
您可以注册为:
var container = new Container();
var app = this.GetInstance<Microsoft.Office.Interop.Excel.Application>("Application");
var appicationProvider = new ApplicationProvider(app);
container.RegisterSingleton<IApplicationProvider>(appicationProvider);
//Make other registrations....
container.Verify();
为了可读性,我做了一个小辅助方法:
public TInstance GetInstance<TInstance>(string key) where TInstance : class
{
return this.GetHostItem<TInstance>(typeof (TInstance), key);
}
你现在需要应用程序对象的任何地方你都可以注入 IApplicationProvider
并像这样使用:
class SomeService
{
private readonly IApplicationProvider applicationProvider;
public SomeService(IApplicationProvider applicationProvider)
{
this.applicationProvider = applicationProvider;
}
public int GetWorkbookCount()
{
return this.currentApplication.Workbooks.Count;
}
// c# 6 syntax
private Excel.Application currentApplication =>
this.applicationProvider.CurrentApplication;
}
已使用 Office 2016 进行测试,这按预期工作。
当试图从我的 Simple Injector 容器解析类型时,它抛出一个 ActivatorException
说我的类型没有注册,虽然我很确定它已经注册了。
ThisAddin.cs
private void ThisAddIn_Startup(object sender, EventArgs e)
{
var container = new Container();
container.RegisterSingleton<Microsoft.Office.Interop.Excel.Application>(() => this.GetHostItem<Microsoft.Office.Interop.Excel.Application>(
typeof(Microsoft.Office.Interop.Excel.Application), "Application"));
var application = container.GetInstance<IApplicationAdapter>();
}
在另一个大会中,在这种情况下 ExcelInterface
。
ApplicationAdapter.cs
internal class ApplicationAdapter : IApplicationAdapter
{
public Application(Microsoft.Office.Interop.Excel.Application excelApplication)
{
}
}
我ApplicationAdapter.cs
public interface IApplicationAdapter
{
}
但是在解决 Excel.Application
时,我得到的异常是:
所以尝试调试这个我认为它实际上没有被正确注册,但是当检查容器中添加的注册时我可以看到 Excel.Application
已经被添加:
我还检查并 100% 确定这两个 类 引用的是同一个 Excel.Application
程序集。
最后我将 Excel.Application
实例添加到容器中,但由于这是 __COMObject
我无法将其注册为 Excel.Application
.
我完全不知道为什么 Simple Injector 无法正确解析接口。
我不确定为什么会这样。我可以确认在您的示例中尝试注册时发生异常。
对于你正在尝试做的事情,我同意史蒂文的评论,哎呀!!在应用程序对象上创建您自己的、可能的多个抽象应该是可行的方法。
不过,只需稍作改动即可实现您想要的效果。您可以像这样注册一个 IApplicationProvider
,而不是注册应用程序对象本身(它会因某些奇怪的原因而抛出):
internal interface IApplicationProvider
{
Excel.Application CurrentApplication { get; }
}
class ApplicationProvider : IApplicationProvider
{
public ApplicationProvider(Excel.Application application)
{
this.CurrentApplication = application;
}
// c# 6 syntax
public Excel.Application CurrentApplication { get; }
}
您可以注册为:
var container = new Container();
var app = this.GetInstance<Microsoft.Office.Interop.Excel.Application>("Application");
var appicationProvider = new ApplicationProvider(app);
container.RegisterSingleton<IApplicationProvider>(appicationProvider);
//Make other registrations....
container.Verify();
为了可读性,我做了一个小辅助方法:
public TInstance GetInstance<TInstance>(string key) where TInstance : class
{
return this.GetHostItem<TInstance>(typeof (TInstance), key);
}
你现在需要应用程序对象的任何地方你都可以注入 IApplicationProvider
并像这样使用:
class SomeService
{
private readonly IApplicationProvider applicationProvider;
public SomeService(IApplicationProvider applicationProvider)
{
this.applicationProvider = applicationProvider;
}
public int GetWorkbookCount()
{
return this.currentApplication.Workbooks.Count;
}
// c# 6 syntax
private Excel.Application currentApplication =>
this.applicationProvider.CurrentApplication;
}
已使用 Office 2016 进行测试,这按预期工作。