如何设置一个包含 winforms 和 web 项目的解决方案?
在我的解决方案中,我有几个项目:
- 一个核心项目。该项目包含我的所有类和接口
- Winforms 项目
- Web 项目 该
应用程序的一个关键功能是动态生成控件。我有一个带有枚举的类,并且必须根据枚举值返回特定的控件。所以我在核心项目中创建了一个工厂,如下所示:
public IControl Create(Enum enum)
{
switch(enum)
{
case "enum.A":
return new CheckBoxControl();
case "enum.B":
return new RadioControl();
}
}
你可能已经猜到了,我有自定义控件。它们都继承自接口(IControl)。但在本例中,CheckBoxControl 和 RadioControl 是 WinFroms 控件。
现在,这些控件位于核心项目中。我不想要这个,因为它是一个核心库,我希望这个库独立于平台。
我想要 WinCore 项目中的 winforms 控件和 WebCore 项目中的 WebControls。问题是,如何从核心项目返回正确的控件?
WebCore 和 WinCore 项目都需要对核心项目的引用,因为核心项目包含我的实体。这意味着我无法从 web 或 wincore 项目的核心设置引用。
怎么解决这个问题呢?
In my solution I have a few projects:
- A core project. This project contains all my classes and interfaces
- A Winforms project
- A Web project
A key feature of the application is to dynamically generate controls. I have a class with an enum, and based on an enum value a particular control must be returned. So I've created a factory in the core project like this:
public IControl Create(Enum enum)
{
switch(enum)
{
case "enum.A":
return new CheckBoxControl();
case "enum.B":
return new RadioControl();
}
}
Ass you might have guessed, I have custom controls. They all inherit from an Interface (IControl). But in this case, CheckBoxControl and RadioControl are WinFroms controls.
Now, these controls resides in the core project. I don't want this, because it is a core library and I want this library to be platform independent.
I want the winforms controls in a WinCore project and the WebControls in a WebCore project. The problem is, How can I return the right controls from the core project?
Both, the WebCore and WinCore project need a reference to the core project, because the core project contains my entities. This means, that I can't set a reference from the core the web- or wincore project.
How to solve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我会这样做:
.Core 应该是一个包含业务的程序集。
.Shared 应该是一个包含独立于平台和技术的基础结构、基类和接口的程序集 - 因此这将让您在任何项目中引用它,避免不必要的依赖 -.< /em>
.Web 应该是包含面向 Web 的功能的程序集
.Web.Forms 应该是仅包含 Web 窗体和 Web 控件的程序集。
.Windows 应该是包含面向 Windows 的功能的程序集。
.Windows.Forms 应该是仅包含 Windows 窗体和控件的程序集。
具有这样的程序集结构,IControl 接口应位于 .Shared 程序集中,并且应由 .Core 引用,从而允许代码添加 IControl 实例而不需要特定于技术的依赖项。
另外,这个解决方案足以让.Windows、.Windows.Forms、.Web和.Web.Forms 参考.Core 和/或.Shared。
更新:这只是一个建议,但是为什么你在工厂中使用枚举?你可以这样做:
你觉得怎么样?没关系,这只是一个建议,因为也许通过一些重构,你可以使用这种工厂方法,但我可以理解这是与您当前的实施相去甚远。更好地集中精力回答我的问题:)
更新 2:
控制反转如何帮助您解决问题?
事实上,如果您注册控制组件的反转,您将通过类型或某些唯一标识符来访问它们。
假设您有
IControl
接口(服务),并且 WindowsTextBox 和 WebFormsTextBox 都实现了IControl
。在您的配置文件中,您将有两个组件,它们具有相同的服务类型(接口)和两种不同的实现,并且它们将标有两个不同的标识符:现在,您已在控制反转容器中注册了两个控件,并且可以使用自己的 API 组件检索工厂,如下所示:
IoCFactory.GetComponents()
。您希望在当前控制反转容器中实现所有 IControl 实现 - 在您的情况下不推荐! -.IoCFactory.GetComponent("WindowsTextBox")
。您需要名为“WindowsTextBox”的 IControl 实现。在第二种情况下,这是我们现在的重点,您将获得一个类型为 IControl 的对象,这意味着您可以访问其公共成员(属性、方法、事件...)。
你的问题中控制反转的点在哪里?请注意,您使用的工厂类将放置在共享库中,以便您可以在任何地方使用它,对于IControl接口也是如此。
是的,我想你需要具体的控制实例。您可以做两件事:
只需使用 IControl 实例,并在特定于技术的逻辑中将其转换为其具体类型 - 例如,WindowsTextBox -
创建尽可能多的接口来具体化更多的IControl,以便某些逻辑可以访问更接近具体控制功能集的一些属性和方法。 一个例子是 ITextBox 接口,并通过这个更具体的接口以与我上面解释的相同的方式获取控制组件的任何反转。
我相信我给出了足够的提示,以便了解我的解决方案结构和装配组织以及控制反转如何为您提供技术独立性,以便您在项目层之间和内部进行查找! ;)
I would do that:
.Core should be an assembly containing business.
.Shared should be an assembly containing infraestructure, base classes and interfaces that are platform and technology-independent - so this will let you referene it in any project avoiding unwanted dependencies -.
.Web should be the assembly containing web-oriented functionality
.Web.Forms should be the assembly containing Web Forms and Web Controls only.
.Windows should be the assembly contaning Windows-oriented functionality.
.Windows.Forms should be the assembly contaning Windows Forms and Controls only.
Having such assembly structure, IControl interface should be in .Shared assembly and this should be referenced by .Core, allowing code to add IControl instances without needing technology-specific dependencies.
In addition, this solution is enough to let .Windows, .Windows.Forms, .Web and .Web.Forms reference .Core and/or .Shared.
UPDATE:It's just a suggestion, but why are you using an enumeration in your factory? You could do that:
What do you think?Nevermind that, it was just a suggestion because maybe, with some refactoring, you could use this kind of factory method, but I can understand this is far from your current implementation. Concentrate better in my answer :)
UPDATE 2:
How inversion of control can help you in your problem?
In fact, if you register inversion of control components, you're going to access them by type or by some unique identifier.
Let's say you've the
IControl
interface (the service) and WindowsTextBox and WebFormsTextBox both implementingIControl
. In your configuration file you're goint to have two components, which have both same service type (the interface) and two different implementations and these will be marked with two different identifiers:Now you've both controls registered in your inversion of control container, and you can use own-API component retrieval factory like this:
IoCFactory.GetComponents<IControl>()
. You want all IControl implementations in current inversion of control's container - not recommended in your case! -.IoCFactory.GetComponent<IControl>("WindowsTextBox")
. You want the IControl implementation called "WindowsTextBox".In the second case, which is our focus now, you get an object typed as IControl, meaning you can access to its common members (properties, methods, events...).
Where's the point of inversion of control in your problem? Note you're using a factory class that would be placed in a shared library so you can use it anywhere, and same for IControl interface.
Right, I guess you need concrete control instances. You can do two things:
Just play with IControl instances and wherever, in a technology-specific logic, cast it to its concrete type - for example, WindowsTextBox - and go on.
Create as many interfaces that concrete more IControl, so some logic can access to some properties and methods that are closer to the concrete control feature set. An example of that would be a ITextBox interface and get any inversion of control component by this more concrete interface in the same way as I explained above.
I believe I gave enough hints in order to get an idea of how my solution structure and assembly organization, plus inversion of control, can give you such technology independence that you're looking between and within your project's layers! ;)
使用 RegisterControls 方法将 Controlmanager 添加到核心。 Webcore 调用 Controlmanager.RegisterControls 方法。主应用程序仅与核心对话
Add a Controlmanager to core with a method RegisterControls. Webcore calls the Controlmanager.RegisterControls method. The main app only talks to core
您应该在 WinForms 项目和 Web 项目中使用不同的工厂。创建在两个工厂中实现的
IControlFactory
接口,并在每个项目中实例化适当类型的工厂。You should use a different factory in the WinForms project and in the Web project. Create a
IControlFactory
interface that is implemented in both factories, and instantiate the appropriate type of factory in each project.