.NET IoC:实际程序执行期间创建的寄存器类型实例

发布于 2024-12-07 19:54:37 字数 1878 浏览 1 评论 0原文

我仍在尝试掌握 IoC,而且我想在程序流/类型解析需要构建的方式方面,我实际上走在完全错误的轨道上。

我有一个几乎以“旧方式”编写的 WinForms 应用程序,我想使用 Autofac 将其转换为 IoC 结构以供练习。
它由一个主窗体组成,可以从中打开登录对话框,成功连接到服务器后,可以使用 Web 服务从 UI 对服务器执行各种功能。

如下所示:

    [STAThread]
    private static void Main()
    {
        Autofac.IContainer container = buildContainer();

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(container.Resolve<Form>());
    }

    private static Autofac.IContainer buildContainer()
    {
        ContainerBuilder builder = new ContainerBuilder();

        builder.RegisterType<MainForm>().As<Form>().SingleInstance();
        builder.Register(c => new LogonDialog());

        IContainer container = builder.Build();

        return container;
    }

我已经开始通过注册 MainFormLogonDialog 类来配置 Autofac 容器,因此 Program.cs 中的代码 >MainForm 构造函数采用 Func,稍后用于在 using 子句中实例化登录对话框。这有效。

我现在陷入以下困境:

成功登录后,LogonDialog 返回一个 Connection 对象,该对象保存有关与服务器建立的连接的各种信息。它的属性之一是对 Web 服务 (IBackendWebservice) 的引用,然后将其传递给实现应用程序各种功能的其他对象(模糊地以 ViewModel/Controller 方式)。所以我可能有一个像 FindRecordController(IBackendWebservice dbservice) 这样的构造函数。

转换的下一步可能是在容器中连接这些控制器类型,除此之外,我当然希望注册 IBackendWebservice 实例,以便每当接口出现时它都可以自动解析被引用。现在的问题显然是,当我最终拥有 IBackendWebservice 对象时,容器已经构建完毕,无法接受任何新的注册(而且我无论如何也没有对它的引用)在我的 MainForm 中)。

我现在想到的一件事是,我可能必须为 Connection 类连接一个工厂委托并将其传递给 LogonDialog,因此容器有一个对我正在使用的 Connection 对象的引用。但是我该如何将 IBackendWebservice 接口注册为该 Connection 实例的属性呢?当通过登录对话框建立新连接时,如何确保 Connection 实例可以并且将会被替换,但不会在 Connection 类型被替换的任何其他地方解决了吗?
这个想法有任何意义吗?

感谢您的任何*指点。

I'm still trying to get to grips with IoC, and I suppose I'm actually on the completely wrong track here concerning the way program flow/type resolution needs to be structured.

I have a WinForms application written pretty much "the old way" which I want to convert to an IoC structure using Autofac for practice purposes.
It consists of a main form from which a logon dialog can be opened, and after successfully connecting to a server, various functions can be performed against the server from the UI using a web service.

I have started configuring the Autofac container by registering the MainForm and LogonDialog classes, so my code in Program.cs looks like this:

    [STAThread]
    private static void Main()
    {
        Autofac.IContainer container = buildContainer();

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(container.Resolve<Form>());
    }

    private static Autofac.IContainer buildContainer()
    {
        ContainerBuilder builder = new ContainerBuilder();

        builder.RegisterType<MainForm>().As<Form>().SingleInstance();
        builder.Register(c => new LogonDialog());

        IContainer container = builder.Build();

        return container;
    }

The MainForm constructor takes a Func<LogonDialog> which is later used to instantiate the logon dialog in a using clause. This works.

I am now stuck at the following point:

After successful logon, the LogonDialog returns a Connection object that holds various information about the connection made to the server. One of its properties is a reference to the web service (IBackendWebservice) which is then passed to other objects that implement the various functionalities of the application (vaguely in a ViewModel/Controller manner). So I might have a constructor like FindRecordController(IBackendWebservice dbservice).

The next step in my conversion would probably be wiring up those controller types in the container, and along with those, I would of course like to have the IBackendWebservice instance registered so it can be automatically resolved whenever the interface is referenced. The problem now is obviously that at the point when I finally have the IBackendWebservice object, the container has already been built and can't accept any new registrations (and I don't have a reference to it anyway in my MainForm).

One thing that came to my mind right now is that I probably have to wire up a factory delegate for the Connection class and pass it to the LogonDialog, so the container has a reference to the Connection object I'm working with. But how would I then have to register the IBackendWebservice interface as a property of that Connection instance ? And how would I make sure the Connection instance can and will be replaced when a new connection is made through the logon dialog, but not in any other place the Connection type is being resolved ?
Does this thought make any sense at all ?

Thanks for any *pointers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

﹏半生如梦愿梦如真 2024-12-14 19:54:37

您可以通过让 LogonDialog 依赖于 ConnectionContainer(它具有 Connection 属性)来通过设计传达您的意图。只有可以设置连接的类型才会依赖它。其他类型将像往常一样依赖 Connection,但您可以直接从容器解析它:(

builder.RegiserType<ConnectionContainer>();
builder.Register(c => c.Resolve<ConnectionContainer>().Connection).AsSelf();

根据需要修改 scpoing)。

You can communicate your intent through your design by letting LogonDialog take a dependency on a ConnectionContainer, which has a Connection property. Only types that may set the connection will take a dependency on it. Other types will take a dependency on Connection as they always did, but you can resolve it directly from the container:

builder.RegiserType<ConnectionContainer>();
builder.Register(c => c.Resolve<ConnectionContainer>().Connection).AsSelf();

(with scpoing modified as needed).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文