我的Windows窗体应用程序中有一个文本框和一个按钮。当按下开始键并在文本框中输入值时,应使用该值打开一个新表格。我想为每个打开的表单创建一个范围。当我关闭表格时,我想关闭相关范围。
如何使用简单的注入器创建自定义范围?
这是一个简单的示例代码
static class Program
{
static readonly Container container;
static Program()
{
container = new Container();
container.Register<MyProgram>();
//??
container.Register<MyCustomClass>(Lifestyle.Scoped);
container.Verify();
}
static void Main()
{
//Something...
}
}
class User
{
public int UserID { get; set; }
public string UserName { get; set; }
}
class MyCustomClass
{
User _user;
public MyCustomClass(User user)
{
_user = user;
}
public void Print()
{
Console.WriteLine(_user.UserName);
}
}
class MyProgram
{
public void StartNewScope(string username, int userid)
{
//Start a new scope for this user
}
//End parameter can be different...
public void EndScope(string username)
{
//End relevant scpoe
}
}
答案 0 :(得分:1)
Simple Injector中的默认作用域机制为环境。这意味着您可以创建一个范围,并且可以在该范围的 context 中的任何位置解析实例。当您有某种请求时,这种方法非常有用,并且在特定的“气泡”中,只需要范围。
但是,在使用Win Forms时,当您希望让每个带有其依赖项的Form都生活在其自己的范围内时,此模型不太直观,因为Form并不生活在孤立的上下文中,例如线程或异步上下文。在这种情况下,环境范围将不起作用。
this great answer中给出了解决此问题的可能方法。规定的解决方案是将表单注册为临时表单,并避免将任何范围内的依赖项作为表单对象图的一部分。相反,您确保在按下按钮时启动作用域,该作用域将在按钮事件结束时终止。正如答案所描述的,这可以使用组成根目录中的一些基础结构代码来完成。
我强烈建议该解决方案,因为它为表格带来了一种有趣的体系结构样式,该样式基于SOLID原理,并且具有优势,解决了典型应用程序存在的许多可维护性问题。
但是,如果不是这样,则可以在Simple Injector中切换到无环境范围。
这需要三件事:
ScopedLifestyle.Flowing
生活方式Scope
实例Scope
实例中解析以下代码显示了这一操作:
var container = new Container();
// Uses the non-ambient scoped lifestyle
container.Options.DefaultScopedLifestyle = ScopedLifestyle.Flowing;
container.Register<MyCustomClass>(Lifestyle.Scoped);
container.Register<MyForm>();
container.Verify();
using (var scope = new Scope(container))
{
var form = scope.GetInstance<MyForm>();
form.ShowDialog();
}
有时候表单的生命周期不清楚,这将在您调用Form.Show()
而不是Form.ShowDialog
时发生。在这种情况下,您可以通过钩住Closed
事件来将范围的生存期与Form的生存期联系起来。 .NET关闭并处理该表单时,Scope
及其所有Scoped
依赖项也会随之消失。
您可以执行以下操作:
var scope = new Scope(container);
var form = scope.GetInstance<MyForm>();
from.Closed += (s, e) => scope.Dispose();