When attempting to resolve a type from my Simple Injector container it is throwing an ActivatorException
saying that my type is not registered although I am fairly sure that it has been.
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>();
}
In another Assembly, in this case ExcelInterface
.
ApplicationAdapter.cs
internal class ApplicationAdapter : IApplicationAdapter
{
public Application(Microsoft.Office.Interop.Excel.Application excelApplication)
{
}
}
IApplicationAdapter.cs
public interface IApplicationAdapter
{
}
But when it comes to resolve the Excel.Application
I get the exception as:
So trying to debug this I thought that it hadn't actually been registered correctly, but when checking the added registrations in the container I can see that the Excel.Application
has been added:
I've also checked and made 100% sure that the two classes are referencing the same Excel.Application
assembly which they are.
Finally I would have added the Excel.Application
instance to the container but since this is a __COMObject
I am unable to register it as an Excel.Application
.
I'm totally at a loss to why Simple Injector is unable to correctly resolve the interface.
I'm not sure why this happens. I can confirm that an exception occurs when trying to register this as in your example.
With what you're trying to do, I agree with Steven's comment, yuck!! Creating your own, possible multiple, abstractions over the application object should be the way to go.
However what you want is possible with some minor changes. Instead of registering the application object itself, which throws for some strange reason, you could register a IApplicationProvider
like this:
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; }
}
Which you can register as:
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();
I made a little helper method for readability:
public TInstance GetInstance<TInstance>(string key) where TInstance : class
{
return this.GetHostItem<TInstance>(typeof (TInstance), key);
}
Everywhere you now need the application object you can just inject the IApplicationProvider
and use like this:
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;
}
Tested with Office 2016 and this works as expected.