.NET IoC:实际程序执行期间创建的寄存器类型实例
我仍在尝试掌握 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;
}
我已经开始通过注册 MainForm
和 LogonDialog
类来配置 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以通过让
LogonDialog
依赖于ConnectionContainer
(它具有Connection
属性)来通过设计传达您的意图。只有可以设置连接的类型才会依赖它。其他类型将像往常一样依赖Connection
,但您可以直接从容器解析它:(根据需要修改 scpoing)。
You can communicate your intent through your design by letting
LogonDialog
take a dependency on aConnectionContainer
, which has aConnection
property. Only types that may set the connection will take a dependency on it. Other types will take a dependency onConnection
as they always did, but you can resolve it directly from the container:(with scpoing modified as needed).