У меня очень похожий проект (за исключением того, что я не использую Caliburn), и я пытался выяснить, как это сделать. Я придумал один метод, который хорошо работает для внедрения в конструктор, используя метод InScope () от Ninject.
У меня есть статический класс, называемый IoC, который обертывает доступ к ядру Ninject. Поскольку все зависимости внедряются в конструктор, контекст имеет значение только при создании объекта. Так что не имеет значения, что предоставляется для контекста, но Guid чувствует себя как безопасный выбор. Program.OpenSession () - статический метод для открытия новой ISession.
public static class Ioc
{
private static readonly IKernel _kernel;
static IoC()
{
_kernel = new StandardKernel();
_kernel.Load(new ContextModule());
}
private static object _context;
public static T ResolveInContext<T>(object context)
{
_context = context;
var result = _kernel.Get<T>();
_context = null;
return result;
}
private class ContextModule : NinjectModule
{
public override void Load()
{
Bind<ISession>().ToMethod(x => Program.OpenSession()).InScope(x => _context);
Bind<frmCompanyViewer>().ToSelf().InScope(x => _context);
}
}
}
Использование:
var frm = IoC.ResolveInContext<frmCompanyViewer>(Guid.NewGuid());
Подпись конструктора формы:
public frmCompanyViewer(ISession session, ICompanyRepository companyRepository)
Я убедился, что с привязкой InScope к той же ISession, которая используется для создания frmCompanyViewer, также используется для создания companyRepository. Если я удаляю InScope, то используются две сессии ISession.
Отредактировано, чтобы добавить: Это также будет работать, см. Комментарии. Это должно быть сделано потокобезопасным для реального применения. Я изменил имя метода на ConstructInContext
, чтобы уточнить, что контекст применяется только во время создания объекта.
public static T ConstructInContext<T>()
{
_context = Guid.NewGuid();
var result = _kernel.Get<T>();
_context = null;
return result;
}