解决COM互操作类型时的SimpleInjector ActivatorException

时间:2016-02-04 11:43:22

标签: c# excel simple-injector

尝试从我的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)
    {
    }
}

IApplicationAdapter.cs

public interface IApplicationAdapter
{
}

但是当谈到解决Excel.Application我得到的例外情况为:

enter image description here

所以试图调试这个我认为它实际上没有正确注册,但是当检查容器中添加的注册时,我可以看到已添加Excel.Application

enter image description here

我还检查并100%确定这两个类引用的是相同的Excel.Application程序集。

最后我会将Excel.Application实例添加到容器中,但由于这是__COMObject,我无法将其注册为Excel.Application

我完全不知道为什么Simple Injector无法正确解析界面。

1 个答案:

答案 0 :(得分:3)

我不确定为什么会这样。我可以确认尝试在您的示例中注册时发生异常。

根据你的努力,我同意史蒂文的评论,哎!!在应用程序对象上创建自己的,可能的多个抽象应该是要走的路。

然而,您想要的是一些微小的变化。您可以注册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进行测试,这可以按预期工作。