如何结合依赖注入可设计组件 [英] How to combine designable components with dependency injection

查看:163
本文介绍了如何结合依赖注入可设计组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在创建一个可设计的.NET组件,您需要提供一个默认的构造函数。从 IComponent的文档:

When creating a designable .NET component, you are required to provide a default constructor. From the IComponent documentation:

要成为一个组成部分,一类必须   实现IComponent的接口和   提供了一个基本的构造   不需要参数或单   类型的IContainer的参数。

To be a component, a class must implement the IComponent interface and provide a basic constructor that requires no parameters or a single parameter of type IContainer.

这使得它无法通过构造函数参数做的依赖注入。 (额外的构造可以提供,但设计师会忽略它们。)我们正在考虑一些选择:

This makes it impossible to do dependency injection via constructor arguments. (Extra constructors could be provided, but the designer would ignore them.) Some alternatives we're considering:

  • 服务定位器

不要使用依赖注入,而是使用Service Locator模式获得的依赖。这似乎正是IComponent.Site。<一个href="http://msdn.microsoft.com/en-us/library/system.iserviceprovider.getservice.aspx">GetService是。我想我们可以创建一个可重复使用的ISite实现(ConfigurableServiceLocator?),它可以提供必要的相关性进行配置。但是如何在设计师的背景下,这个工作?

Don't use dependency injection, instead use the service locator pattern to acquire dependencies. This seems to be what IComponent.Site.GetService is for. I guess we could create a reusable ISite implementation (ConfigurableServiceLocator?) which can be configured with the necessary dependencies. But how does this work in a designer context?

通过属性依赖注入

通过属性注入依赖。 提供默认情况下,如果他们 必要显示在一个组件 设计师。文件的属性 需要被注入。

Inject dependencies via properties. Provide default instances if they are necessary to show the component in a designer. Document which properties need to be injected.

注入与初始化方法依赖

这很像是通过注射的属性,但它一直需要在一个地方被注入的依赖关系的清单。这种方式所需的依赖关系的清单记录暗示,编译器会协助您有错误时,该列表的变化。

This is much like injection via properties but it keeps the list of dependencies that need to be injected in one place. This way the list of required dependencies is documented implicitly, and the compiler will assists you with errors when the list changes.

任何想法,最好的做法是什么吗?你怎么办呢?

Any idea what the best practice is here? How do you do it?


修改:我已删除(例如一个WinForms用户控件)因为我打算这个问题是关于通用部件。组件是所有关于控制反转(见 UMLv2规范第8.3.1 ),所以我不认为你不应该注入任何服务是一个很好的答案。


edit: I have removed "(e.g. a WinForms UserControl)" since I intended the question to be about components in general. Components are all about inversion of control (see section 8.3.1 of the UMLv2 specification) so I don't think that "you shouldn't inject any services" is a good answer.


修改2 :它采取了一些演奏与WPF和MVVM模式终于搞定马克的回答。我现在看到的可视化控件确实是一个特例。对于使用非可视化组件的设计表面,我觉得.NET组件模型与依赖注入根本不相容的。这似乎是设计围绕服务定位器模式代替。也许这将开始改变与该是在<一个附加在.NET 4.0中的基础设施建设href="http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.aspx">System.ComponentModel.Composition命名空间。


edit 2: It took some playing with WPF and the MVVM pattern to finally "get" Mark's answer. I see now that visual controls are indeed a special case. As for using non-visual components on designer surfaces, I think the .NET component model is fundamentally incompatible with dependency injection. It appears to be designed around the service locator pattern instead. Maybe this will start to change with the infrastructure that was added in .NET 4.0 in the System.ComponentModel.Composition namespace.

推荐答案

这同一个问题窃听我很长一段时间,直到我意识到,我是想在一个错误的方式。 AFAIR,对于creaing一个IComponent的执行的唯一原因是提供设计时功能 - 有IComponent的实现没有运行时效果

This same question bugged me for a long time until I realized that I was thinking about it in a wrong way. AFAIR, the only reason for creaing an IComponent implementation is to provide design-time features - there's no run-time effect of IComponent implementations.

通过corrolary,这意味着你应该多为创建组件来实现设计时的功能。特别是对于控件,这意味着你可以的配置的组件的行为以某种方式。这是非常重要的是要认识到这是一个完全不同的关注不是如何组件的实际行为或者数据则显示。它不应该在设计时的行为,也不应包含的数据。

By corrolary, this means that you should mostly create components to implement design-time features. Particularly for Controls, this means that you can configure the component to behave in a certain way. It is very important to realize that this is a completely different concern than how the component actually behaves or which data it displays. It should not have behavior at design-time, and nor should it contain data.

因此​​,在构造函数的约束其实是一种幸福,因为它会指示你重新考虑你的设计。 A控制是一个数据源无关的软件比显示和以某种方式的数据交互。只要数据符合某些接口等的控制是幸福的。 如何的数据到达时没有关注到控制的,也不应该这样。这将是一个错误,让数据是如何装载和修改的控制控制。

As such, the constraint on the constructor is actually a blessing, since it instructs you to rethink your design. A Control is a data-source agnostic piece of software than displays and interacts with data in a certain way. As long as that data conforms to certain interfaces, etc. the Control is happy. How that data arrives is of no concern to the Control, and neither should it be. It would be an error to let the Control control how data is loaded and modified.

在WPF中,这比Windows窗体中明确更清晰的:你给一个特定的控制一个DataContext和控件绑定到的DataContext成员的属性。在DataContext(其可以是任何对象)源自控制之外;这就是责任或presentation层。

In WPF, this is explicitly much clearer than in Windows Forms: You give a particular Control a DataContext and bind properties of the Control to members of that DataContext. The DataContext (which can be any object) originates from outside the Control; that's the responsibility or your Presentation Layer.

在Windows窗体,你仍然可以通过指定数据上下文控件这样做。从本质上讲,这是地产注入 - 要知道,你不应该注射服务;你应该注入的数据的。

In Windows Forms, you can still do the same by assigning a data context to a Control. Essentially, this is Property Injection - just be aware that you should not inject services; you should inject data.

总之,我会去你的建议也没有。相反,我们的控制有一个或多个属性,允许您将数据分配到控制,并使用数据绑定绑定反对这种数据。该控件的实现内部时,prepared处理的情况下没有数据:这会发生在每次控制是通过VS在设计时托管的时间。该空对象模式实现这种韧性非常有用的。

In summary, I would go with neither of your suggestions. Instead, let the Control have one or more properties that allow you to assign data to the Control, and use databinding to bind against this data. Inside the Control's implementation, be prepared to handle the situation where there's no data: This will occur every time the Control is hosted by VS at design-time. The Null Object pattern very useful for implementing such resilience.

然后,建立从控制器的数据上下文。这是做它的MVC方式:控制是查看,但你应该有一个独立的控制器,可以实例化并分配模型视图

Then, set up the data context from your Controllers. That's the MVC way of doing it: The Control is the View, but you should have a separate Controller that can instantiate and assign a Model to the View.

这篇关于如何结合依赖注入可设计组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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