I am trying to configure DI for a VSTO Excel project.
The generated code for this worksheet offers me an event called "Launch", which is not suitable for installing event handlers for events such as "Launch", "Change", "BeforeDoubleClick", etc.
I think that as a rule, good practice avoids code in code files.
What I do is create external classes that are responsible for manipulating the sheet and calling external code, such as web services, databases and domain logic.
I can successfully create a Factory that will be used by the codebehind file and create an instance of the worksheet logic class.
For example:
//...inside Sheet1.cs private IExpenseWorksheetFactory _factory; void ExpensesBeforeRightClick(Excel.Range target, ref bool cancel) { Application.EnableEvents = false; var popup = _factory.CreateContextMenu(); popup.ShowContextMenu(target, ref cancel); Application.EnableEvents = true; } // ... rest of Sheet1.cs
The code above is inside the file with the code created by Visual Studio, and minimally. Responsibility for displaying a pop-up window is delegated to a single object. The Factory object is responsible for communicating with Ninject and getting the object for me. This proxy is generated automatically using the Ninject.Extensions.Factory project, as I am passing this interface:
/// <summary> /// Abstract Factory for creating Worksheet logic objects. Meant to be used with Ninject Factory extension. /// </summary> public interface IExpenseWorksheetFactory { ExpenseWorksheet CreateWorksheet(); ExpenseWorksheet.ContextMenus CreateContextMenu(); ExpenseWorksheet.Events CreateEventHandlers(); }
In the application launch, I defined bindings and bindings for Factory itself:
//instantiate the kernel in app Composition Root _kernel = new StandardKernel(); //worksheet related stuff - seems to be ok to be singleton _kernel.Bind<ExpenseWorksheet>().ToSelf().InSingletonScope(); _kernel.Bind<ExpenseWorksheet.Events>().ToSelf().InSingletonScope(); _kernel.Bind<ExpenseWorksheet.ContextMenus>().ToSelf().InSingletonScope(); //"automagic" factories _kernel.Bind<IExpenseWorksheetFactory>().ToFactory();
The problem is this:
How can I insert this Factory into the generated code of a VSTO sheet? I don't like the idea of calling _kernel.Get<IExpenseWorksheetFactory> inside the Startup method on a worksheet. Can I search for all available instances of Sheet1 and force paste factory?