Bar*_*ran 1 .net c# dependency-injection winforms simple-injector
我的 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
}
}
Run Code Online (Sandbox Code Playgroud)
简单注入器中的默认作用域机制是环境的。这意味着您可以创建一个范围,并且在该范围的上下文中的任何位置都可以解析实例。当您有某种请求,并且在特定的“泡沫”内,只有所需的范围时,这非常有效。
然而,当使用 Win Forms 时,当您想让每个 Form 及其依赖项存在于其自己的范围内时,此模型不太直观,因为 Form 并不存在于隔离的上下文中,例如线程或异步上下文。在这种情况下,环境作用域不起作用。
这个伟大的答案给出了这个问题的可能解决方案。规定的解决方案是将表单注册为瞬态,并防止将任何作用域依赖项作为表单对象图的一部分。相反,您可以确保按下按钮时启动作用域,并在按钮事件结束时结束作用域。正如答案所描述的,这可以使用作为组合根一部分的一些基础设施代码来完成。
我强烈建议该解决方案,因为它带来了一种基于 SOLID 原则的有趣的架构风格,并且作为优势,解决了典型应用程序存在的许多可维护性问题。
但是,如果这不是一个选项,则可以在简单注入器中切换到无环境范围。
这需要三件事:
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();
}
Run Code Online (Sandbox Code Playgroud)
有时 Form 的生命周期并不那么明确,当您调用Form.Show()
而不是 时,就会发生这种情况Form.ShowDialog
。在这种情况下,您可以通过挂钩事件将范围的生命周期与表单的生命周期联系起来Closed
。当 .NET 关闭并处理表单时,Scope
其所有Scoped
依赖项也将关闭并处理。
您可以按如下方式执行此操作:
var scope = new Scope(container);
var form = scope.GetInstance<MyForm>();
from.Closed += (s, e) => scope.Dispose();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1793 次 |
最近记录: |