在Web窗体中创建自定义简单注入器作用域 [英] Creating custom Simple Injector Scope in Web Forms

查看:82
本文介绍了在Web窗体中创建自定义简单注入器作用域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Windows窗体应用程序中有一个文本框和一个按钮。当按下开始键并在文本框中输入值时,应使用该值打开一个新表格。我想为每个打开的表单创建一个范围。当我关闭表单时,我想关闭相关范围。

I have a text box and a button in my Windows forms application. When the start key is pressed with the value written in the textbox, a new Form should be opened with this value. I want to create a scope for each opened form. And when I close the form I want to close the relevant scope.

如何使用简单的注射器创建自定义范围?

How do I create a custom scope with the simple injector?

这是一个简单的示例代码

Here is a simple sample code

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
    }
}


推荐答案

Simple Injector中的默认作用域机制为环境。这意味着您可以创建一个范围,并且可以在该范围的 context 中的任何位置解析实例。当您有某种要求时,此功能非常有用,并且在特定的气泡中,仅需要一定范围。

The default scoping mechanism in Simple Injector is ambient. This means that you can create a scope, and anywhere within the context of that scope, you can resolve instances. This works great when you have a request of some sort, and within that particular 'bubble', there is only on scope required.

但是,此模型不太直观当使用Win Forms时,由于每个Form都不存在于隔离的上下文(例如线程或异步上下文)中,因此您希望让每个具有其依赖关系的Form都驻留在其自己的范围内。在那种情况下,环境范围将不起作用。

This model, however, is less intuitive when working with Win Forms, when you want to let each Form with its dependencies live in its own scope, since a Form does not live in an isolated context, such as thread or asynchronous context. In that case ambient scoping does not work.

这个好答案。规定的解决方案是将表单注册为临时表单,并避免将任何范围内的依赖项作为表单对象图的一部分。相反,您确保在按下按钮时启动作用域,该作用域将在按钮事件结束时终止。可以按照答案中的描述使用组成根目录中的一些基础结构代码来完成此操作。

A possible solution to this problem is given in this great answer. The prescribed solution is to register forms as transient and prevent having any scoped dependencies as part of the Form's object graph. Instead, you ensure that a scope is started when a button is pressed, which will end when the button event ends. This can be done, as the answer describes, using some infrastructural code that's part of your Composition Root.

我强烈建议该解决方案,因为它带来了有趣的建筑风格以SOLID原则为基础的表格,并具有优势,解决了典型应用程序存在的许多可维护性问题。

I can highly advise that solution, because it brings an interesting architectural style to the table that is based around the SOLID principles, and as advantage, solves many maintainability issues typical applications have.

但是,如果这不是一个选择,那就是可以在Simple Injector中切换到无环境范围。

If that, however, is not an option, it is possible to switch to ambient-less scoping in Simple Injector.

这需要三件事:


  • 使用 ScopedLifestyle.Flowing 生活方式

  • 手动创建 Scope 实例

  • 直接从 Scope 实例解析

  • Using the ScopedLifestyle.Flowing lifestyle
  • Manually creating Scope instances
  • Resolving directly from a Scope instance

以下代码显示了这一点:

The following code shows this in action:

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 事件将范围的生命周期与窗体的生命周期联系起来。 .NET关闭并处理该表单时, Scope 也会具有其所有 Scoped 依赖性。

Sometimes the lifetime of a Form isn't that clear, which will happens when you call Form.Show() instead of Form.ShowDialog. In that case you can tie the lifetime of the scope to that of the Form by hooking onto the Closed event. When .NET closes and disposes the form, so will the Scope with all its Scoped dependencies.

您可以执行以下操作:

var scope = new Scope(container);

var form = scope.GetInstance<MyForm>();

from.Closed += (s, e) => scope.Dispose();

这篇关于在Web窗体中创建自定义简单注入器作用域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆