2012-09-07 2 views
7

Я пытаюсь настроить DI для проекта VSTO Excel.Инъекция зависимостей внутри Excel VSTO и Ninject.Extensions.Factory

Сгенерированный код для данного рабочего листа предлагает мне событие Startup, которое позволяет устанавливать обработчики событий для таких событий, как Startup, Change, BeforeDoubleClick и т. Д.

Я думаю, что в целом хорошая практика избегает кода в файлах с кодом.
Что я делаю, это создавать внешние классы, которые несут ответственность за манипулирование листом и вызов внешнего кода, например, веб-сервисов, баз данных и логики домена.

Я могу успешно создать Factory, который будет использоваться файлом codebehind и создать экземпляр класса логики рабочего листа.

Например:

//...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 

код выше внутри файл кода Visual Studio генерирует и это минимальный. Ответственность за отображение всплывающего окна делегируется отдельному объекту. Объект фабрики отвечает, чтобы поговорить с Ninject и получить объект для меня. Этот прокси генерируется автоматически с помощью Ninject.Extensions.Factory проекта, как я прохожу интерфейс вроде этого:

/// <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(); 
} 

В запуске приложения, я определил привязки и обязательную для самого завода:

//instantiate the kernel in app's 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(); 

Проблема:

Как я могу ввести эту фабрику в сгенерированный код листа VSTO? Мне не нравится идея вызвать _kernel.Get<IExpenseWorksheetFactory> внутри метода запуска на рабочем листе. Можно ли искать все доступные экземпляры Sheet1 и принудительно вводить завод?

ответ

2

Короткий ответ: Нет

Вы ищете что-то вроде инъекции конструктора, который читает по общему признанию, более элегантно. Но это невозможно, потому что у вас нет доступа к c'tor в добавлении VSTO.

Но так или иначе, что плохого в звонке _kernel.Get<IExpenseWorksheetFactory>? В конце концов, вызов контейнера DI явно для разрешения зависимости является одним из его нормальных вариантов использования, а файл с кодовым записями выполняется именно для этого: подключение к сети.

Вы правы, что код не должен содержать никакой бизнес-логики, но, с другой стороны, он определенно должен содержать, содержащий весь код, необходимый для подключения. Это основная причина, почему она существует. Или, другими словами:

Я думаю, что в целом хорошая практика избегает кода в файлах с кодом.

не соответствует действительности во всех случаях (но только для подавляющего большинства из них), и вы не должны переусердствовать здесь. Если вы это сделаете, вы окажетесь в борьбе с системой - и помните, что система всегда побед; -) ...

+0

Согласен ... Основное внимание всегда уделяется решению бизнес-задач, а не борьбе против системы и рамок! –

+0

Как невозможно введение конструктора? Обработчик событий запуска VSTO - это то, где вы должны настроить ninject, а затем вы можете использовать DI для всех ваших объектов сервиса и хранилища, а также форм. –

Смежные вопросы