我有一个非常相似的项目(除了我没有使用 Caliburn)并且一直在尝试弄清楚如何做到这一点。我确实提出了一种使用 Ninject 的 InScope() 方法很好地用于构造函数注入的方法。
我有一个名为 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,用于构造 frmCompanyViewer 的同一 ISession 也用于构造 companyRepository。如果我删除 InScope,则使用两个 ISession。
编辑添加:这也可以,请参阅评论。对于真正的应用程序,这应该是线程安全的。我更改了方法名称以ConstructInContext
澄清上下文仅适用于对象构造期间。
public static T ConstructInContext<T>()
{
_context = Guid.NewGuid();
var result = _kernel.Get<T>();
_context = null;
return result;
}